<!DOCTYPE html>
<html lang="en">

<!-- Head tag -->
<head><meta name="generator" content="Hexo 3.9.0">

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!--Description-->
    

    <!--Author-->
    
        <meta name="author" content="ck">
    

    <!--Open Graph Title-->
    
        <meta property="og:title" content="CK&#39;s blogs">
    

    <!--Open Graph Description-->
    

    <!--Open Graph Site Name-->
    <meta property="og:site_name" content="CK&#39;s blogs">

    <!--Type page-->
    
        <meta property="og:type" content="website">
    

    <!--Page Cover-->
    

    <meta name="twitter:card" content="summary">
    

    <!-- Title -->
    
    <title>page - CK&#39;s blogs</title>

    <!-- Bootstrap Core CSS -->
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" integrity="sha384-y3tfxAZXuh4HwSYylfB+J125MxIs6mR5FOHamPBG064zB+AFeWH94NdvaCBm8qnd" crossorigin="anonymous">

    <!-- Custom Fonts -->
    <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" type="text/css">

    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

    <!-- Gallery -->
    <link href="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.css" type="text/css" rel="stylesheet">

    <!-- Custom CSS -->
    <link rel="stylesheet" href="/blog/css/style.css">

    <!-- Google Analytics -->
    


</head>


<body>

<div class="bg-gradient"></div>
<div class="bg-pattern"></div>

<!-- Menu -->
<!--Menu Links and Overlay-->
<div class="menu-bg">
    <div class="menu-container">
        <ul>
            
            <li class="menu-item">
                <a href="/blog/">
                    Home
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/archives">
                    Archives
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/2019/09/04/本人简历/">
                    About
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/tags">
                    Tags
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/categories">
                    Categories
                </a>
            </li>
            
            <li class="menu-item">
                <a href="/blog/contact.html">
                    Contact
                </a>
            </li>
            
        </ul>
    </div>
</div>

<!--Hamburger Icon-->
<nav>
    <a href="#menu"></a>
</nav>

<div class="container">

    <!-- Main Content -->
    <div class="row">
    <div class="col-sm-12">

        <!--Title and Logo-->
        <header>
    <div class="logo">
        <a href="/blog/"><i class="logo-icon fa fa-cube" aria-hidden="true"></i></a>
        
            <h1 id="main-title" class="title">CK's blogs</h1>
        
    </div>
</header>

        <section class="main">
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/03/06/爬虫的概念祥解/">
                爬虫的概念祥解
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-03-06</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>爬虫系统分为如下3种类型：</p>
<p>批量型爬虫：<br>批量型爬虫有比较明确的抓取范围和目标，当爬虫达到这个设定的目标后，即停止抓取过程。至于具体目标可能各异，也许是设定抓取一定数量的网页即可，也许是设定抓取的时间等，各不一样。</p>
<p>增量型爬虫：<br>增量型爬虫与批量型爬虫不同，会保持持续不断的抓取，对于抓取到的网页，要定期更新，因为互联网网页处于不断变化中，新增网页、网页被删除或者网页内容更改都很常见，而增量型爬虫需要及时反映这种变化，所以处于持续不断的抓取过程中，不是在抓取新网页，就是在更新已有网页。通用的商业搜索引擎爬虫基本都属此类。</p>
<p>垂直型爬虫：<br>垂直型爬虫关注特定主题内容或者属于特定行业的网页，比如对于健康网站来说，只需要从互联网页面里找到与健康相关的页面内容即可，其他行业的内容不在考虑范围。垂直型爬虫一个最大的特点和难点就是：如何识别网页内容是否属于指定行业或主题。从节省系统资源的角度来讲，不可能把所有互联网页面下载之后在进行筛选，这样会造成资源过度浪费，往往需要爬虫在抓取阶段就能够动态识别某个网址是否与主题相关，并尽量不去抓取无关页面，以达到节省资源的目的。垂直搜索网站或者垂直行业网站往往需要此种类型的爬虫。</p>
<p>优秀爬虫的特性<br>优秀爬虫的特性对于不同的应用来说，可能实现的方式各有差异，但是实用的爬虫都应该具备以下特性：<br>01高性能<br>互联网的网页数量是海量的。所以爬虫的性能至关重要，这里的性能主要是指爬虫下载网页的抓取速度，常见的评价方式是以爬虫每秒能够下载的网页数量作为性能指标，单位时间能够下载的网页数量越多，爬虫的性能越高。要提高爬虫的性能，在设计时程序访问磁盘的操作方法及具体实现时数据结构的选择很关键，比如对于待抓取URL队列和已抓取URL队列，因为URL数量非常大，不同实现方式性能表现迥异，所以高效的数据结构对于爬虫性能影响很大。<br>02可扩展性<br>即使单个爬虫的性能很高，要将所有网页都下载到本地，仍然需要相当长的时间周期，为了能够尽可能缩短抓取周期，爬虫系统应该有很好地可扩展性，即很容易通过增加抓取服务器和爬虫数量来达到此目的。目前实用的大型网络爬虫一定是分布式运行的，即多台服务器专做抓取，每台服务器部署多个爬虫，每个爬虫多线程运行，通过多种方式增加并发性。对于巨型的搜索引擎服务商来说，可能还要在全球范围、不同地域分别部署数据中心，爬虫也被分配到不同的数据中心，这样对于提高爬虫系统的整体性能是很有帮助的。<br>03健壮性<br>爬虫要访问各种类型的网站服务器，可能会遇到很多种非正常情况，比如网页HTML编码不规范， 被抓取服务器突然死机，甚至爬虫陷阱等。爬虫对各种异常情况能否正确处理非常重要，否则可能会不定期停止工作，这是无法忍受的。从另外一个角度来讲，假设爬虫程序在抓取过程中死掉，或者爬虫所在的服务器宕机，健壮的爬虫应能做到，再次启动爬虫时，能够恢复之前抓取的内容和数据结构，而不是每次都需要把所有工作完全从头做起，这也是爬虫健壮性的一种体现。<br>04友好性<br>爬虫的友好性包含两方面的含义：一是保护网站的部分私密性，另一是减少被抓取网站的网络负载。爬虫抓取的对象是各类型的网站，对于网站所有者来说，有些内容并不希望被所有人搜到，所以需要设定协议，来告知爬虫哪些内容是不允许抓取的。目前有两种主流的方法可达到此目的：爬虫禁抓协议和网页禁抓标记。</p>
<p>爬虫禁抓协议<br>指的是由网站所有者生成一个指定的文件robot.txt，并放在网站服务器的根目录下，这个文件指明了网站中哪些目录下的网页是不允许爬虫抓取的。具有友好性的爬虫在抓取该网站的网页前，首先要读取robot.txt文件，对于禁止抓取的网页不进行下载。<br>网页禁抓标记一般在网页的HTML代码里加入meta name=”robots”标记，content字段指出允许或者不允许爬虫的哪些行为。可以分为两种情形，一种是告知爬虫不要索引该网页内容，以noindex作为标记；另外一种情形是告知爬虫不要抓取网页所包含的链接，以nofollow作为标记。通过这种方式，可以达到对网页内容的一种隐私保护。<br>遵循以上协议的爬虫可以被认为是友好的，这是从保护私密性的角度来考虑的。另外一种友好性则是，希望爬虫对某网站的访问造成的网路负载较低。爬虫一般会根据网页的链接连续获取某网站的网页，如果爬虫访问网站频率过高，会给网站服务器造成很大的访问压力，有时候甚至会影响网站的正常访问，造成类似DOS攻击的效果，为了减少网站的网络负载，友好性的爬虫应该在抓取策略部署时考虑每个被抓取网站的负载，在尽可能不影响爬虫性能的情况下，减少对单一站点短期内的高频访问。</p>
<p>爬虫质量的评价标准<br>如果从搜索引擎用户体验的角度考虑，对爬虫的工作效果有不同的评价标准，其中最主要的3个标准是：<br>1、抓取网页的覆盖率<br>2、抓取网页时新性<br>3、抓取网页重要性。</p>
<p>数据流（流程，类似抓取任务生命周期）</p>
<p>Scrapy中的数据流由执行引擎控制，其过程如下:<br>1.引擎打开一个网站(open adomain)，找到处理该网站的Spider并向该spider请求第一个要爬取的URL(s)。<br>2.引擎从Spider中获取到第一个要爬取的URL并在调度器(Scheduler)以Request调度。<br>3.引擎向调度器请求下一个要爬取的URL。<br>4.调度器返回下一个要爬取的URL给引擎，引擎将URL通过下载中间件(请求(request)方向)转发给下载器(Downloader)。<br>5.一旦页面下载完毕，下载器生成一个该页面的Response，并将其通过下载中间件(返回(response)方向)发送给引擎。<br>6.引擎从下载器中接收到Response并通过Spider中间件(输入方向)发送给Spider处理。<br>7.Spider处理Response并返回爬取到的Item及(跟进的)新的Request给引擎。<br>8.引擎将(Spider返回的)爬取到的Item给ItemPipeline，将(Spider返回的)Request给调度器。<br>9.(从第二步)重复直到调度器中没有更多地request，引擎关闭该网站。</p>
<p>分布式爬虫<br>Scrapy-Redis是一个基于Redis的Scrapy分布式组件.它利用Redis对用于爬取的请求(Requests)进行存储和调度(Schedule)，并对爬取产生的项目(items)存储以供后续处理使用,scrapy-redi重写了scrapy一些比较关键的代码,将scrapy变成一个可以在多个主机上同时运行的分布式爬虫。</p>
<p>代理ip<br>当爬取速度过快时，当请求次数过多时都面临ip被封的可能。因此使用代理也是必备的。</p>
<p>代理池的概念<br>抓取市面上所有免费代理网站的ip，比如西刺代理，快代理等<br>代理池维护存储 redis 因为代理ip生命周期很短，属于热数据，不适合持久化存储<br>使用时随机取出一个代理ip使用</p>
<p>使用request加代理<br>import requests<br>proxies = { “http”: “<a href="http://10.10.1.10:3128&quot;" target="_blank" rel="noopener">http://10.10.1.10:3128&quot;</a>,<br>            “https”: “<a href="http://10.10.1.10:1080&quot;,}" target="_blank" rel="noopener">http://10.10.1.10:1080&quot;,}</a><br>p = request.get(“<a href="http://www.baidu.com&quot;" target="_blank" rel="noopener">http://www.baidu.com&quot;</a>, proxies = proxies)<br>print(p.content.decode(‘utf-8’))</p>
<p>抓取App端数据<br>使用Charles抓包<br>软件地址 <a href="https://www.charlesproxy.com/download/" target="_blank" rel="noopener">https://www.charlesproxy.com/download/</a><br>为什么选择Charles 跨平台，方便好用，可以抓取Android应用也可以抓取Ios<br>可以抓取http https</p>
<p>抓取视频<br>使用三方库 you-get<br>配合Fiddler抓包来抓取视频流</p>
<p>应对反爬<br>headers头文件<br>有些网站对爬虫反感，对爬虫请求一律拒绝，这时候我们需要伪装成浏览器，通过修改http中的headers来实现<br>伪造Cookie<br>模拟登陆<br>一般登录的过程都伴随有验证码，这里我们通过selenium自己构造post数据进行提交，将返回验证码图片的链接地址输出到控制台下，点击图片链接识别验证码，输入验证码并提交，完成登录</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/03/04/Redissearch结合python3做全文检索功能服务/">
                Redissearch结合python3做全文检索功能服务
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-03-04</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="使用Redisearch实现的全文检索功能服务"><a href="#使用Redisearch实现的全文检索功能服务" class="headerlink" title="使用Redisearch实现的全文检索功能服务"></a>使用Redisearch实现的全文检索功能服务</h1><p><a href="https://v3u.cn/" target="_blank" rel="noopener">首页</a> - <a href="https://v3u.cn/l_id_1" target="_blank" rel="noopener">Python</a> /2019-08-29</p>
<p>​    “检索”是很多产品中无法绕开的一个功能模块，当数据量小的时候可以使用模糊查询等操作凑合一下，但是当面临海量数据和高并发的时候，业界常用 elasticsearch 和 lucene 等方案，但是elasticsearch对运行时内存有着最低限额，其运行时大小推荐 2G 以上的内存空间，并且需要额外的磁盘空间做持久化存储。</p>
<p>​    其实mongoDB 内置的正则匹配搜索文本以及自带的 text 索引和 search 关键字也是一套靠谱的解决方案，但是这一次我们带来一种更加高效经济的文本检索方案：Redisearch</p>
<p>​    下图是elasticsearch和redisearch的性能对比</p>
<p>​    <img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190829/20190829025837_90896.png" alt="img"></p>
<p>​    Redis Modules 是 redis 4.0 引入的一种扩展机制，用户可以通过实现 redis module 提供的 C api 接口为 redis 服务添加定制化功能。 redisLab 也希望籍此来规范 redis 社区的 ecosystem 实现。<br>    redis module 本身的版本独立于redis，并且以编译成动态加载库 .so 文件的方式 release， 不同版本的 redis 可以 load 同一版本 module.so 文件。<br>    redis 提供了两种加载方式。可以通过 在 conf 文件中 加入 loadmodule /path/to/mymodule.so ，也可以在 redis-cli中使用命令 MODULE LOAD /path/to/panda.so 动态加载，MODULE UNLOAD 卸载。</p>
<p>​    特性<br>    基于文档的全文索引。<br>    高性能增量索引。<br>    支持文档评分，文档字段(field) 权重机制。<br>    支持布尔复杂查询。<br>    支持自动补全。<br>    基于 snowball 的词干分析，多语言支持。使用 friso 支持中文分词。<br>    utf-8 字符集支持。<br>    redis 数据持久化支持。<br>    自定义评分机制。</p>
<p>​    </p>
<p>​    其原理是在 redis 的 hashmap 基础上就可以很容易实现倒排索引的结构。redisearch 倒排索引除了实现了基础功能外，还引入了内存管理等优化功能。如果有兴趣可以阅读源码中的 src/inverted_index.c 部分</p>
<p>​    </p>
<p>​    首先，安装Rediseach,记住一点你本地的redis服务版本必须在4.0以上，网上一大堆编译安装的攻略，繁琐又浪费时间，所以又到了Docker登场时间了，hub上有编译好的免费镜像供我们下载</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull redislabs/redisearch</span><br></pre></td></tr></table></figure>

<p>​    下载后，直接在后台启动服务</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -d -p 6666:6379 redislabs/redisearch:latest</span><br></pre></td></tr></table></figure>

<p>​    <img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190829/20190829025426_73540.png" alt="img"></p>
<p>​    此时已经有一个docker容器在后台启动了，redis服务映射到了宿主的6666端口，我们来连接一下</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">redis-cli -h localhost -p 6666</span><br></pre></td></tr></table></figure>

<p>​    <img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190829/20190829023916_11652.png" alt="img"></p>
<p>​    检查 modules 是否成功加载</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">localhost:6666&gt; MODULE list</span><br><span class="line">1) 1) &quot;name&quot;</span><br><span class="line">   2) &quot;ft&quot;</span><br><span class="line">   3) &quot;ver&quot;</span><br><span class="line">   4) (integer) 10405</span><br></pre></td></tr></table></figure>

<p>​    如果返回数组中存在 “ft” ， 则表明 redisearch 已经成功加载。</p>
<p>​    Redisearch 的索引概念 与elasticsearch 的 index 类似，表示某一类文档资源单元。<br>    这里我们定义了一个 SMARTX_VM 索引，其中存储的文档 包含 了 title 和 desc 两个 类型为 TEXT 的field。</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">FT.CREATE SMARTX_VM SCHEMA title TEXT WEIGHT 5.0 desc TEXT</span><br></pre></td></tr></table></figure>

<p>​    然后向刚刚创建的这条索引加一个文档</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">FT.ADD SMARTX_VM vm-2019082911110001 1.0 LANGUAGE &quot;chinese&quot; FIELDS title &quot;人工智能&quot; desc &quot;我在北京昌平学习人工智能&quot;</span><br></pre></td></tr></table></figure>

<p>​    LANGUAGE “chinese” 参数 表示 使用 中文分词器 处理文本。默认为英文</p>
<p>​    此时我们进行文档检索</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">FT.SEARCH SMARTX_VM &quot;人工智能&quot; LANGUAGE &quot;chinese&quot;</span><br></pre></td></tr></table></figure>

<p>​    注意检索的时候也要指定语言，这里我们用中文分词，默认的英文分词是无法检索中文的</p>
<p>​    <img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190829/20190829025024_22484.png" alt="img"></p>
<p>​    可以看到已经返回了我们想要的结果。</p>
<p>​    Redisearch 是一个高效，功能完备的内存存储的高性能全文检索组件， 十分适合应用在数据量适中， 内存和存储空间有限的环境。借助数据同步手段，我们可以很方便的将redisearch 结合到现有的数据存储中， 进而向产品提供 全文检索， 自动补全等服务优化功能。</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/03/01/在centos7-6上部署前后端分离项目Nginx反向代理vue-js2-6-Tornado5-1-1，使用supervisor统一管理服务/">
                在centos7.6上部署前后端分离项目Nginx反向代理vue.js2.6+Tornado5.1.1，使用supervisor统一管理服务
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-03-01</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="centos7-6上部署前后端分离项目Nginx反向代理vue-js2-6-Tornado5-1-1，使用supervisor统一管理服务"><a href="#centos7-6上部署前后端分离项目Nginx反向代理vue-js2-6-Tornado5-1-1，使用supervisor统一管理服务" class="headerlink" title="centos7.6上部署前后端分离项目Nginx反向代理vue.js2.6+Tornado5.1.1，使用supervisor统一管理服务"></a>centos7.6上部署前后端分离项目Nginx反向代理vue.js2.6+Tornado5.1.1，使用supervisor统一管理服务</h1><p><a href="https://v3u.cn/" target="_blank" rel="noopener">首页</a> - <a href="https://v3u.cn/l_id_4" target="_blank" rel="noopener">Mac &amp; Linux</a> /2019-08-22</p>
<p>​    这一次使用vue.js+tornado的组合来部署前后端分离的web项目，vue.js不用说了，前端当红炸子鸡，泛用性非常广，无论是单页应用，还是混合式开发app，亦或是微信小程序开发，样样得心应手，tornado最近的风头有点被新锐框架sanic抢走了，但是作为老牌的异步非阻塞框架，其内置了支持epoll/kqueue 等高效网络库，而具备了处理高并发的能力并且开发效率也不低，这一次tornado作为承载后端压力的角色。</p>
<p>​    首先部署前端，将测试好的vue.js2.6项目打包，值得一提的是，在生产环境并不需要node.js服务，因为利用vue.js的特性可以对前端页面进行打包，使其成为一个纯静态页包，上线后利用nginx对其代理即可，既方便又安全。在项目目录下执行npm run build命令，在执行之前，先把conifg目录下index.js中的bulid配置../dist改成./dist</p>
<p><img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190822/20190822125312_62859.png" alt="img"></p>
<p>​    执行命令后，会在项目的config目录下的dist目录生成静态页，将dist目录上传到服务器的/root目录下</p>
<p>​    运行 chmod 755 /root/dist 对项目文件授权</p>
<p>​    然后，在线上安装nginx</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">#设置源</span><br><span class="line">sudo rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm</span><br><span class="line"></span><br><span class="line">#安装</span><br><span class="line">yum install -y nginx</span><br><span class="line"></span><br><span class="line">#启动服务</span><br><span class="line">systemctl start nginx.service</span><br></pre></td></tr></table></figure>

<p>​    服务器需要暴露80端口，此时，测试一下，看看能否显示欢迎页</p>
<p>​    <img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190822/20190822125636_42282.png" alt="img"></p>
<p>​    没有问题，这时修改一下nginx 配置文件 vim /etc/nginx/conf.d/default.conf  增加下面的配置，这里前端服务默认监听80端口</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">server &#123;</span><br><span class="line">    listen       80;</span><br><span class="line">    server_name  localhost;</span><br><span class="line"></span><br><span class="line">    access_log      /root/md_vue_access.log;</span><br><span class="line">    error_log       /root/md_vue_error.log;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    client_max_body_size 75M;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    location / &#123;</span><br><span class="line"></span><br><span class="line">        root /root/dist;</span><br><span class="line">        index index.html;</span><br><span class="line">        try_files $uri $uri/ /index.html;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    error_log    /root/dist/error.log    error;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">#继续修改配置</span><br><span class="line">vim /etc/nginx/nginx.conf</span><br><span class="line">将第一行改为 user root;</span><br></pre></td></tr></table></figure>

<p>改好后，重启nginx服务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl reload nginx.service</span><br></pre></td></tr></table></figure>

<p>每次修改nginx配置一定要重启服务，否则修改不会生效</p>
<p>访问一下，看看效果</p>
<p><img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190822/20190822131209_18271.png" alt="img"></p>
<p>​    至此，前端就部署好了，是不是很简单呢？这一次我们摒弃了老美多商城丑陋而原始的模板，采用响应式设计的新模板，兼容任意大小屏幕，并且还可以打包成apk，简直棒</p>
<p>​    接着，我们来部署后端，首先安装python3，需要注意的是centos自带python2.7，当装软件的时候千万不要影响这个python2.7，因为系统很多东西都依赖python2，所以我们只要python2和python3共存就可以了</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">yum install epel-release</span><br><span class="line"></span><br><span class="line">yum install python36</span><br><span class="line"></span><br><span class="line">wget --no-check-certificate https://bootstrap.pypa.io/get-pip.py</span><br><span class="line"></span><br><span class="line">python3 get-pip.py</span><br><span class="line"></span><br><span class="line">pip3 install pymysql</span><br><span class="line"></span><br><span class="line">pip3 install pillow</span><br><span class="line"></span><br><span class="line">pip3 install pycryptodome</span><br><span class="line"></span><br><span class="line">pip3 install tornado==5.1.1</span><br><span class="line"></span><br><span class="line">pip3 install sqlalchemy</span><br></pre></td></tr></table></figure>

<p>​    将tornado项目上传到/root/mytornado下，修改项目权限:chmod -R 755 /root/mytornado 然后将项目的debug模式关闭，并且修改端口号为8001，同时阿里云暴露8001端口，进行项目根目录，启动服务:python3 server.py，检查一下</p>
<p><img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190823/20190823013951_52792.png" alt="img"></p>
<p>​    没有问题，此时修改nginx配置文件，用nginx对tornado进行反向代理，新建一个配置文件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/nginx/conf.d/tornado.conf</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">upstream tornado &#123;</span><br><span class="line">    server 127.0.0.1:8001;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">server &#123;</span><br><span class="line">    listen   8000;</span><br><span class="line">    root /root/mytornado;</span><br><span class="line">    index server.py index.html;</span><br><span class="line"></span><br><span class="line">    server_name server;</span><br><span class="line"></span><br><span class="line">        # 静态文件直接由Nginx处理</span><br><span class="line">    location /static/&#123;</span><br><span class="line">        alias /root/mytornado/static/;</span><br><span class="line">        expires 24h;</span><br><span class="line">    &#125;</span><br><span class="line">    location /&#123;</span><br><span class="line">        proxy_pass_header Server;</span><br><span class="line">        proxy_set_header Host $http_host;</span><br><span class="line">        proxy_redirect off;</span><br><span class="line">        proxy_set_header X-Real-IP $remote_addr;</span><br><span class="line">        # 把请求方向代理传给tornado服务器，负载均衡</span><br><span class="line">        proxy_pass http://tornado;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该配置的意思就是由nginx监听8000端口，并且将请求反向代理至tornado服务，这里我们只起了一个8001的服务，还可以启动更多，这就是传统意义上的负载均衡</p>
<p>重启一下nginx</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl restart nginx.service</span><br></pre></td></tr></table></figure>

<p>访问服务器的8000端口，阿里云也别忘了暴露一下8000</p>
<p><img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190823/20190823022030_20802.png" alt="img"></p>
<p>​    最后，每次手动在命令行启动应用是比较麻烦的，我们还需要一个能够方便的管理服务进程的工具，包括自动重启进程等，而Supervisor的作用在这里就可以体现了。我们使用它来管理这个Tornado web server相关的进程</p>
<p>​    安装supervisor</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">yum install epel-release</span><br><span class="line">yum install -y supervisor</span><br></pre></td></tr></table></figure>

<p>​    生成配置文件</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">supervisord -c /etc/supervisord.conf</span><br></pre></td></tr></table></figure>

<p>​    修改配置文件</p>
<p>​    然后修改配置文件 vim /etc/supervisord.conf   将下面几行的注释解开</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[inet_http_server]         ; inet (TCP) server disabled by default</span><br><span class="line">port=*:9001        ; (ip_address:port specifier, *:port for all iface)</span><br><span class="line">username=user              ; (default is no username (open server))</span><br><span class="line">password=123               ; (default is no password (open server))</span><br></pre></td></tr></table></figure>



<p>​    然后在配置文件末尾加上tornado的配置</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">[program:mytornado]</span><br><span class="line">command=python3 /root/mytornado/server.py --port=8001</span><br><span class="line">directory=/root/mytornado</span><br><span class="line">autorestart=true</span><br><span class="line">redirect_stderr=true</span><br></pre></td></tr></table></figure>

<p>​    保存文件退出后，启动supervisor服务</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">supervisord -c /etc/supervisord.conf</span><br></pre></td></tr></table></figure>

<p>​    此时，将刚刚手动启动的tornado服务关闭，然后访问服务器的9001端口，用配置文件中的账号和密码登录</p>
<p><img src="https://v3u.cn/v3u/Public/js/editor/attached/image/20190823/20190823024429_56609.png" alt="img"></p>
<p>​    这样就可以在管理页面中控制tornado服务了，同时supervisor还赋予了守护进程模式，方便服务拉起</p>
<p>​    需要注意的是，当修改了supervisor的配置，想要生效就得重启supervisor服务，终止服务命令是：</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">killall -s INT /usr/bin/python</span><br></pre></td></tr></table></figure>

<p>​    因为supervisor是基于python2的，所以不用担心python3的进程</p>
<p>​    另外如果只想在命令行中控制tornado也是可以的</p>
<p>​    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">#停止tornado服务</span><br><span class="line">supervisorctl stop mytornado</span><br><span class="line"></span><br><span class="line">#启动tornado服务</span><br><span class="line">supervisorctl start mytornado</span><br></pre></td></tr></table></figure>

<p>至此，我们通过nginx反向代理tornado负载均衡，并且通过supervisor管理就部署好了</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/02/23/爬虫部署-scrapyd部署爬虫-Gerapy管理界面scrapyd-gerapy部署流程/">
                爬虫部署---scrapyd部署爬虫+Gerapy管理界面scrapyd+gerapy部署流程
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-02-23</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>———scrapyd部署爬虫—————<br>1.编写爬虫<br>2.部署环境<br>pip install scrapyd<br>pip install scrapyd-client<br>启动scrapyd的服务：cmd:&gt;scrapyd（必须处于开启状态）<br>在爬虫根目录执行：scrapyd-deploy,如果提示不是内部命令，需要修改配置文件。</p>
<p>3.发布工程到scrapyd<br>修改scrapy.cfg，去掉url前的#<br>进入到scrapy项目根目录，执行：scrapyd-deploy <target> -p <projectname>提示：（target:scrapy.cfg中[deploy:***]）（projectname：scrapy.cfg中project = XXX）<br>（#url中的#去掉）<br>4.启动爬虫<br>第一种方法：Django中view.py<br>class StartSpider(View):<br>def get(self,request):<br>url = ‘<a href="http://localhost:6800/schedule.json&#39;" target="_blank" rel="noopener">http://localhost:6800/schedule.json&#39;</a><br>data = {‘project’: ‘ScrapyAbckg’, ‘spider’: ‘abckg’}<br>print( requests.post(url=url, data=data))<br>return JsonResponse({‘result’:’OK’})<br>第二种方法：（命令式启动爬虫：curl <a href="http://localhost:6800/schedule.json" target="_blank" rel="noopener">http://localhost:6800/schedule.json</a> -d project=项目名 -d spider=爬虫名）</projectname></target></p>
<p>5.启动django<br>cmd：python manage.py runserver</p>
<p>—————-scrapyd 管理爬虫接口———————-<br>1、获取状态</p>
<p><a href="http://127.0.0.1:6800/daemonstatus.json" target="_blank" rel="noopener">http://127.0.0.1:6800/daemonstatus.json</a></p>
<p>2、获取项目列表</p>
<p><a href="http://127.0.0.1:6800/listprojects.json" target="_blank" rel="noopener">http://127.0.0.1:6800/listprojects.json</a></p>
<p>3、获取项目下已发布的爬虫列表</p>
<p><a href="http://127.0.0.1:6800/listspiders.json?project=myproject" target="_blank" rel="noopener">http://127.0.0.1:6800/listspiders.json?project=myproject</a></p>
<p>4、获取项目下已发布的爬虫版本列表<br><a href="http://127.0.0.1:6800/listversions.json?project=myproject" target="_blank" rel="noopener">http://127.0.0.1:6800/listversions.json?project=myproject</a></p>
<p>5、获取爬虫运行状态</p>
<p><a href="http://127.0.0.1:6800/listjobs.json?project=myproject" target="_blank" rel="noopener">http://127.0.0.1:6800/listjobs.json?project=myproject</a></p>
<p>6、启动服务器上某一爬虫（必须是已发布到服务器的爬虫)<br><a href="http://localhost:6800/schedule.json" target="_blank" rel="noopener">http://localhost:6800/schedule.json</a><br>(post方式，data={“project”:myproject,”spider”:myspider}）</p>
<p>7、删除某一版本爬虫</p>
<p><a href="http://127.0.0.1:6800/delversion.json" target="_blank" rel="noopener">http://127.0.0.1:6800/delversion.json</a><br>(post方式，data={“project”:myproject,”version”:myversion}）</p>
<p>8、删除某一工程，包括该工程下的各版本爬虫<br>(运行中爬虫无法删除)<br><a href="http://127.0.0.1:6800/delproject.json" target="_blank" rel="noopener">http://127.0.0.1:6800/delproject.json</a><br>(post方式，data={“project”:myproject}）</p>
<p>9.取消运行中的爬虫<br><a href="http://127.0.0.1:6800/cancel.json" target="_blank" rel="noopener">http://127.0.0.1:6800/cancel.json</a><br>(post方式，data={“project”:myproject,”job”:jobid}）</p>
<p>————–django+scrapy—————————–<br>1.创建django项目，并编写models.py,启动django项目</p>
<p>2.Django项目根目录下创建Scrapy项目<br>（这是scrapy-djangoitem所需要的配置）<br>配置Django嵌入，在Scrapy的settings.py中加入以下代码：<br>import os<br>import sys<br>sys.path.append(os.path.dirname(os.path.abspath(‘.’)))<br>os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘django项目名.settings’<br>import django<br>django.setup()</p>
<p>3.编写爬虫<br>4.item.py中引入Django模型类（pip install scrapy-djangoitem）<br>from scrapy_djangoitem import DjangoItem<br>from 子应用 import models<br>class ScrapyabckgItem(DjangoItem):<br># 此处必须起名为django_model,主爬虫中使用item[‘title’]=xxx<br>django_model = models.AbckgModel</p>
<p>5.pipelines.py中调用save()<br>class ScrapyabckgPipeline(object):<br>def process_item(self, item, spider):<br># 插入到数据库<br>item.save()<br>return item #将item传给下一个管道继续处理</p>
<p>6.启动爬虫(用命令，并非scrapyd启动)：scrapy crawl abckg<br>7.刷新django-admin后台</p>
<p>—————Gerapy 管理界面————–</p>
<p>安装：</p>
<p>为什么部署呢？<br>部署会让项目更稳定，更高效，增大访问量</p>
<p>scrapyd部署 和 gerapy部署 的区别<br>相比scrapyd部署的只能查看状态，页面简陋 gerapy更人性化，页面简洁，可操作性强</p>
<p>总结流程：</p>
<p>1启动scrapyd：</p>
<p>　　命令：scrapyd</p>
<p>2启动gerapy：</p>
<p>　　命令：gerapy runserver</p>
<p>3部署爬虫scrapy 到 scrapyd，在爬虫根目录发布爬虫：</p>
<p>　　命令： scrapyd-deploy <target> -p 项目名称</target></p>
<p>4访问gerapy:</p>
<p>　　地址：127.0.0.1:8000</p>
<p>5在gerapy页面 ：</p>
<p>　　主机管理 –》创建 –》连接scrapyd</p>
<p>6在gerapy页面 ：</p>
<p>　　点击调度 —–》 会展示出所有的已发布爬虫</p>
<p>7随意对这些爬虫进行 监管，运行</p>
<p>ok！ 搞定啦！CentOs 部署爬虫在 linux 下同理，只是ip不同罢了 就这！</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/02/12/机器学习三剑客之pandas-numpy/">
                机器学习三剑客之pandas+numpy
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-02-12</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="机器学习"><a href="#机器学习" class="headerlink" title="机器学习"></a>机器学习</h1><h2 id="什么是机器学习？"><a href="#什么是机器学习？" class="headerlink" title="什么是机器学习？"></a>什么是机器学习？</h2><ul>
<li>机器学习是从数据中自动分析获得规律(模型)，并利用规律对未知数据进行预测</li>
</ul>
<h2 id="机器学习存在的目的和价值领域？"><a href="#机器学习存在的目的和价值领域？" class="headerlink" title="机器学习存在的目的和价值领域？"></a>机器学习存在的目的和价值领域？</h2><ul>
<li><h4 id="领域："><a href="#领域：" class="headerlink" title="领域："></a>领域：</h4><ul>
<li>医疗、航空、教育、物流、电商 等。。。</li>
</ul>
</li>
<li><h4 id="目的："><a href="#目的：" class="headerlink" title="目的："></a>目的：</h4><ul>
<li>让机器学习程序替换手动的步骤，减少企业的成本也提高企业的效率</li>
</ul>
</li>
</ul>
<h1 id="jupyter-lab语法使用"><a href="#jupyter-lab语法使用" class="headerlink" title="jupyter lab语法使用"></a><code>jupyter lab</code>语法使用</h1><h1 id="jupyter-lab安装"><a href="#jupyter-lab安装" class="headerlink" title="jupyter lab安装"></a><code>jupyter lab安装</code></h1><p> 命令：pip install jupyterlab</p>
<p>接下来了解下机器学习三剑客的前两位 numpy + pandas 的使用</p>
<p>一、区别<br>Numpy:是数值计算的扩展包，它能高效处理N维数组,复杂函数,线性代数.</p>
<p>Panadas:是做数据处理。市python的一个数据分析包,<br>二、简介<br>1）NumPy：N维数组容器</p>
<p>Numpy专门针对ndarray的操作和运算进行了设计，所以数组的存储效率和输入输出性能远优于Python中的嵌套列表，数组越大，Numpy的优势就越明显。Numpy系统是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵，比Python自身的嵌套列表（nested list structure)结构要高效的多（该结构也可以用来表示矩阵（matrix））。据说NumPy将Python相当于变成一种免费的更强大的MatLab系统。</p>
<p>1.ndarray的优势<br>NumPy提供了一个N维数组类型ndarray，它描述了相同类型的“items”的集合。</p>
<p>一、内存块风格:</p>
<p>这是因为ndarray中的所有元素的类型都是相同的，而Python列表中的元素类型是任意的，所以ndarray在存储元素时内存可以连续，而python原生lis就t只能通过寻址方式找到下一个元素，这虽然也导致了在通用性能方面Numpy的ndarray不及Python原生list，但在科学计算中，Numpy的ndarray就可以省掉很多循环语句，代码使用方面比Python原生list简单的多。</p>
<p>二、ndarray支持并行化运算（向量化运算）</p>
<p>三、Numpy底层使用C语言编写，内部解除了GIL（全局解释器锁），其对数组的操作速度不受Python解释器的限制，效率远高于纯Python代码。</p>
<p>2.Pandas：表格容器<br>pansdas是基于Numpy的一种工具,该工具是为了解决数据分析任务而创建的,。Pandas 纳入了大量库和一些标准的数据模型，提供了高效地操作大型数据集所需的工具。pandas提供了大量快速便捷地处理数据的函数和方法。使Python成为强大而高效的数据分析环境的重要因素之一。<br>-——————–<br>作者：愤怒的马农<br>来源：CSDN<br>原文：<a href="https://blog.csdn.net/weixin_43407092/article/details/89575559" target="_blank" rel="noopener">https://blog.csdn.net/weixin_43407092/article/details/89575559</a><br>版权声明：本文为博主原创文章，转载请附上博文链接！</p>
<h1 id="numpy"><a href="#numpy" class="headerlink" title="numpy"></a><code>numpy</code></h1><h2 id="模块导包"><a href="#模块导包" class="headerlink" title="模块导包"></a>模块导包</h2><ul>
<li><p><code>import numpy as np</code></p>
<ul>
<li>导入<code>numpy</code> 起别名为np</li>
</ul>
</li>
<li><p>列举表格数据</p>
</li>
</ul>
<h2 id="pandas-读取工具"><a href="#pandas-读取工具" class="headerlink" title="pandas : 读取工具"></a>pandas : 读取工具</h2><ul>
<li><h5 id="numpy：释放了GIL锁"><a href="#numpy：释放了GIL锁" class="headerlink" title="numpy：释放了GIL锁"></a><code>numpy</code>：释放了GIL锁</h5><ul>
<li>真正实现了多线程</li>
<li>一些库运行的比较快或计算能力强，一部分原因就是因为<code>numpy</code></li>
</ul>
</li>
<li><h5 id="GIL锁历史遗留问题"><a href="#GIL锁历史遗留问题" class="headerlink" title="GIL锁历史遗留问题"></a>GIL锁历史遗留问题</h5><ul>
<li><p><code>cpython</code> 加了GIL锁</p>
</li>
<li><p><code>jpython</code> 没有GIL锁，（常用）所以不存在遗留问题</p>
</li>
</ul>
</li>
</ul>
<h2 id="数据类型-—–-gt-numpy-ndarray"><a href="#数据类型-—–-gt-numpy-ndarray" class="headerlink" title="数据类型 —–&gt; numpy.ndarray"></a>数据类型 —–&gt; <code>numpy.ndarray</code></h2><h3 id="维度数据"><a href="#维度数据" class="headerlink" title="维度数据"></a>维度数据</h3><ul>
<li><code>np.arange(1000)</code> # 遍历 与for循环range相同作用 生成<code>1-999</code>数据</li>
<li><code>np.array([1,2,3])</code> # 一维数据</li>
<li><code>np.array([[1,2,3],[11,22,33]])</code> # 二维数据</li>
<li><code>np.array([[[1,2,3],[11,22,33]]])</code> # 三维数据</li>
</ul>
<h3 id="维度"><a href="#维度" class="headerlink" title="维度"></a>维度</h3><ul>
<li>维度相当于，多层内包含列表(数组)的数据</li>
<li>超过一维单独存在数据，默认为一维</li>
<li>父级每多一层，维度加一</li>
<li>单个子级每多一层，单个维度层级加一</li>
</ul>
<h3 id="查看维度详情"><a href="#查看维度详情" class="headerlink" title="查看维度详情"></a>查看维度详情</h3><ul>
<li>语法:—–&gt;<code>结果变量.shape</code><ul>
<li>如结果 array([1, 2, 3])<ul>
<li>表示一维3个，二维2个，三维1个数据</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="查看数据维度是几维"><a href="#查看数据维度是几维" class="headerlink" title="查看数据维度是几维"></a>查看数据维度是几维</h3><ul>
<li>语法:—–&gt;<code>结果变量.ndim</code><ul>
<li>结果 是管与结果是几维的 维度数字</li>
</ul>
</li>
</ul>
<h3 id="改变维度"><a href="#改变维度" class="headerlink" title="改变维度"></a>改变维度</h3><ul>
<li>语法:—–&gt;<code>结果.reshape(数值1,数值2)</code><ul>
<li>结果 变为二维 结果为：一个大列表，数值1个数的子列表，子列表内数值2个数的数据<ul>
<li>小总结:可根据需求维度设置多个参数，() 内参数总个数是维度，每个参数依次是每个维度的数据个数</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="生成数据"><a href="#生成数据" class="headerlink" title="生成数据"></a>生成数据</h3><h4 id="生成正太分布数据"><a href="#生成正太分布数据" class="headerlink" title="生成正太分布数据"></a>生成正太分布数据</h4><ul>
<li>语法:—–&gt;<code>np.linspace(起始值,结束值,生成几个数值)</code><ul>
<li>在区间内(括号内前两个参数)生成几个数，间隔区间大小相同，并且都是float64(浮点)类型</li>
</ul>
</li>
<li>把<code>均值为0</code> <code>方差为1</code>的数据分布称为标准正态分布<ul>
<li>例<code>np.random.normal(loc=0,scale=1,size=(2000,3000))</code></li>
</ul>
</li>
<li>正太分布数据<ul>
<li><code>np.random.randn(10)</code></li>
</ul>
</li>
</ul>
<h4 id="生成指定维度，数据随机"><a href="#生成指定维度，数据随机" class="headerlink" title="生成指定维度，数据随机"></a>生成指定维度，数据随机</h4><ul>
<li>语法:—–&gt; <code>np.random.rangint(0,15,size=(5,3))</code><ul>
<li>区间0~14，维度详情指定二维，二维数据5组，一维3组</li>
</ul>
</li>
</ul>
<h4 id="手写指定维度"><a href="#手写指定维度" class="headerlink" title="手写指定维度"></a>手写指定维度</h4><ul>
<li>语法:—–&gt; <code>np.array([[1,2,3],[11,22,33],[1,2,3],[11,22,33],[1,2,3]])</code><ul>
<li>二维 5*3 数据</li>
</ul>
</li>
</ul>
<h4 id="遍历改变维度，生成指定维度"><a href="#遍历改变维度，生成指定维度" class="headerlink" title="遍历改变维度，生成指定维度"></a>遍历改变维度，生成指定维度</h4><ul>
<li>语法:—–&gt; <code>np.arange(12).reshape(4,3)</code><ul>
<li>遍历数值，然后改变维度 二维 4*3数据</li>
</ul>
</li>
</ul>
<h3 id="随机种子，固定随机值"><a href="#随机种子，固定随机值" class="headerlink" title="随机种子，固定随机值"></a>随机种子，固定随机值</h3><ul>
<li><p><code>np.random.seed(10)</code> # 固定的随机值必须是随机数区间内的数值，不然无效</p>
<ul>
<li><code>a = np.random.randint(10,20,size=(5,3))</code> # 每个 一维数据内 能生成一个固定随机值</li>
</ul>
</li>
<li><p>输出展示详情，分析变化</p>
<ul>
<li><p><code>print(&#39;维度:{}&#39;.format(a.ndim))</code></p>
</li>
<li><p><code>print(&#39;大小:{}&#39;.format(a.size))</code></p>
</li>
<li><p><code>print(&#39;尺寸:{}&#39;.format(a.shape))</code></p>
</li>
</ul>
</li>
</ul>
<h2 id="求值"><a href="#求值" class="headerlink" title="求值"></a>求值</h2><h3 id="平均值"><a href="#平均值" class="headerlink" title="平均值"></a>平均值</h3><ul>
<li>语法:—–&gt; <code>np.mean(结果变量)</code></li>
</ul>
<h3 id="绝对值"><a href="#绝对值" class="headerlink" title="绝对值"></a>绝对值</h3><ul>
<li>语法:—–&gt; <code>np.abs(结果变量)</code></li>
</ul>
<h3 id="数量值"><a href="#数量值" class="headerlink" title="数量值"></a>数量值</h3><ul>
<li>语法:—–&gt; <code>count()</code></li>
</ul>
<h3 id="索引值"><a href="#索引值" class="headerlink" title="索引值"></a>索引值</h3><ul>
<li>计算能获取到最大值和最小值的索引(整数)<ul>
<li>语法:—–&gt; <code>argmax</code> 和 <code>argmin</code></li>
</ul>
</li>
<li>计算能获取到最大值和最小值的索引<ul>
<li>语法:—–&gt; <code>idmax</code> 和 <code>idmin</code></li>
</ul>
</li>
</ul>
<h3 id="求和"><a href="#求和" class="headerlink" title="求和"></a>求和</h3><ul>
<li>语法:—–&gt; <code>np.sum(结果变量)</code></li>
</ul>
<h3 id="最大值"><a href="#最大值" class="headerlink" title="最大值"></a>最大值</h3><ul>
<li>语法:—–&gt; <code>np.max(结果变量)</code></li>
</ul>
<h3 id="最小值"><a href="#最小值" class="headerlink" title="最小值"></a>最小值</h3><ul>
<li>语法:—–&gt; <code>np.min(结果变量)</code></li>
</ul>
<h3 id="返回累乘积值"><a href="#返回累乘积值" class="headerlink" title="返回累乘积值"></a>返回累乘积值</h3><ul>
<li>语法:—–&gt; <code>np.cumprod()</code></li>
</ul>
<h3 id="返回累加值"><a href="#返回累加值" class="headerlink" title="返回累加值"></a>返回累加值</h3><ul>
<li>语法:—–&gt; <code>np.cumsum()</code></li>
</ul>
<h2 id="标准差"><a href="#标准差" class="headerlink" title="标准差"></a>标准差</h2><h3 id="什么是标准差？"><a href="#什么是标准差？" class="headerlink" title="什么是标准差？"></a>什么是标准差？</h3><ul>
<li>在概率统计中最常使用作为统计分布程度上的测量。标准差定义是总体各单位标准值与其平均数离差平方的算术平均数的平方根。它反映组内个体间的离散程度。</li>
<li>简单来说，标准差是一组数据平均值分散程度的一种度量。一个较大的标准差，代表大部分数值和其平均值之间差异较大；一个较小的标准差，代表这些数值较接近平均值。</li>
</ul>
<h3 id="求标准差"><a href="#求标准差" class="headerlink" title="求标准差"></a>求标准差</h3><ul>
<li>语法:—–&gt; <code>np.stb(结果变量)</code></li>
</ul>
<h2 id="方差"><a href="#方差" class="headerlink" title="方差"></a>方差</h2><h3 id="什么是方差？"><a href="#什么是方差？" class="headerlink" title="什么是方差？"></a>什么是方差？</h3><ul>
<li>方差用来计算每一个变量（观察值）与总体均数之间的差异。<ul>
<li>为避免出现离均差总和为零，离均差平方和受样本含量的影响，统计学采用平均离均差平方和来描述变量的变异程度。是标准差的平方。</li>
</ul>
</li>
</ul>
<h3 id="求方差"><a href="#求方差" class="headerlink" title="求方差"></a>求方差</h3><ul>
<li>语法:—–&gt; <code>np.val(结果变量)</code></li>
</ul>
<h2 id="切片、索引"><a href="#切片、索引" class="headerlink" title="切片、索引"></a>切片、索引</h2><ul>
<li>指定数据<ul>
<li>根据索引操作，按照普通列表去下标</li>
</ul>
</li>
<li>切片<ul>
<li>语法 —-&gt; <code>结果变量[取哪条][起始位置:结束位置:间隔步数]</code></li>
<li>语法 —-&gt; <code>结果变量[起始位置:结束位置,:数值]</code><ul>
<li>数值 在：之前去除数值列展示，之后再：之后只展示数值列</li>
</ul>
</li>
</ul>
</li>
</ul>
<h1 id="pandas"><a href="#pandas" class="headerlink" title="pandas"></a><code>pandas</code></h1><h2 id="模块导包-1"><a href="#模块导包-1" class="headerlink" title="模块导包"></a>模块导包</h2><ul>
<li><code>import pandas as pd</code><ul>
<li>导入<code>pandas</code> 起别名为<code>pd</code></li>
</ul>
</li>
</ul>
<h2 id="Series"><a href="#Series" class="headerlink" title="Series"></a><code>Series</code></h2><ul>
<li><h3 id="存放一维度数据"><a href="#存放一维度数据" class="headerlink" title="存放一维度数据"></a>存放一维度数据</h3></li>
<li><p>通过list构建Series</p>
<ul>
<li><code>data = pd.Series([1,2,3,4,5,6,7])</code></li>
</ul>
</li>
<li><p>通过range函数，构建Series</p>
<ul>
<li><code>data = pd.Series(range(10,20))</code></li>
</ul>
</li>
</ul>
<h2 id="DataFrame"><a href="#DataFrame" class="headerlink" title="DataFrame"></a><code>DataFrame</code></h2><ul>
<li><h3 id="存放二维度数据"><a href="#存放二维度数据" class="headerlink" title="存放二维度数据"></a>存放二维度数据</h3></li>
<li><p>随机种子，固定随机值为10</p>
<ul>
<li><code>np.random.seed(10)</code></li>
</ul>
</li>
<li><p>随机生成一组5*3 二维数据</p>
<ul>
<li><code>data = np.random.randint(10,20,size=(5,3))</code></li>
</ul>
</li>
<li><p><code>DataFrame</code>存放二维数据</p>
<ul>
<li><code>df_data = pd.DataFrame(data)</code></li>
</ul>
</li>
<li><p><code>columns=[列数相同的值]</code> 给每列起别名</p>
<ul>
<li><code>df_data .columns=[&#39;A&#39;,&#39;B&#39;,&#39;C&#39;]</code></li>
</ul>
</li>
</ul>
<h2 id="删除"><a href="#删除" class="headerlink" title="删除"></a>删除</h2><ul>
<li><p>直接删除整行</p>
<ul>
<li><code>data.drop(索引)``data.drop(索引,inplace=True)</code> <code>inplace=True</code>修改原数据</li>
</ul>
</li>
<li><p>直接删除多行</p>
<ul>
<li><code>data.drop([索引,索引。。。])</code></li>
</ul>
</li>
</ul>
<h2 id="合并"><a href="#合并" class="headerlink" title="合并"></a>合并</h2><ul>
<li><p>小例子：</p>
<ul>
<li><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">data1 = np.array([[1,2,3],[11,22,33],[1,2,3],[11,22,33],[1,2,3]]) # 5*3</span><br><span class="line">data2 = np.arange(12).reshape(4,3)      # 4*3 </span><br><span class="line">data3 = np.random.randint(10,20,size=(4,3))  # 生成制定5*3维度，随机生成数字</span><br><span class="line">data4 = np.random.randint(10,20,size=(4,5))   # 4*5</span><br><span class="line"></span><br><span class="line"># r_ 列合并 c_ 行合并 不符合 会报错</span><br><span class="line">data5 = np.r_[data1,data2]  # r_ 合并 列个数相同  才能合并  5*3  &lt;---&gt;  4*3 否则报错</span><br><span class="line">data6 = np.c_[data3,data4]  # c_ 合并 行个数相同  才能合并  4*3  &lt;---&gt;  4*5 否则报错</span><br></pre></td></tr></table></figure>
</li>
</ul>
</li>
<li><p>小总结：</p>
<ul>
<li>r_ 列合并 列个数相同 才能合并</li>
<li>c_ 行合并 行个数相同 才能合并</li>
<li>否则报错</li>
</ul>
</li>
</ul>
<h2 id="展示"><a href="#展示" class="headerlink" title="展示"></a>展示</h2><ul>
<li>存放后展示</li>
</ul>
<h3 id="展示前几行"><a href="#展示前几行" class="headerlink" title="展示前几行"></a>展示前几行</h3><ul>
<li>语法:—–&gt; <code>data.head()</code></li>
</ul>
<h3 id="展示后几行"><a href="#展示后几行" class="headerlink" title="展示后几行"></a>展示后几行</h3><ul>
<li>语法:—–&gt; <code>data.tail()</code></li>
</ul>
<h3 id="展示前几行-1"><a href="#展示前几行-1" class="headerlink" title="展示前几行"></a>展示前几行</h3><ul>
<li>语法:—–&gt; <code>data.head(数值)</code></li>
</ul>
<h3 id="展示后几行-1"><a href="#展示后几行-1" class="headerlink" title="展示后几行"></a>展示后几行</h3><ul>
<li>语法:—–&gt; <code>data.tail(数值)</code></li>
</ul>
<h2 id="arrary和-asarrary"><a href="#arrary和-asarrary" class="headerlink" title="arrary和 asarrary"></a><code>arrary</code>和 <code>asarrary</code></h2><ul>
<li>区别：<ul>
<li><code>array</code>和<code>asarray</code>都可以将结构数据转化为<code>ndarray</code>，但是主要区别就是当数据源是<code>ndarray</code>时，<code>array</code>仍然会<code>copy</code>出一个副本，占用新的内存，但<code>asarray</code>不会</li>
</ul>
</li>
</ul>
<h2 id="info"><a href="#info" class="headerlink" title="info()"></a><code>info()</code></h2><ul>
<li><code>DataFrame</code>数据的简明摘要</li>
</ul>
<h1 id="CSV"><a href="#CSV" class="headerlink" title="CSV"></a>CSV</h1><h3 id="读取csv和改写csv编码格式"><a href="#读取csv和改写csv编码格式" class="headerlink" title="读取csv和改写csv编码格式"></a>读取csv和改写csv编码格式</h3><ul>
<li>读取文件时，因为python3的原因，默认<code>utf-8</code>，其他格式指定解码<code>encoding=</code><ul>
<li><code>data = pd.read_csv(&#39;51job.csv&#39;,encoding=&#39;ANSI&#39;)</code> 读文件 默认</li>
<li><code>data=pd.read_csv(&#39;51job.csv&#39;,encoding=&#39;utf-8&#39;)</code> 读文件</li>
</ul>
</li>
<li>每次想保存修改数据或修改编码格式，执行以下类型格式代码：<ul>
<li>要在<code>参数括号内</code>加入<code>inplace=True</code>确认修改原数据的参数值</li>
<li><code>data.to_csv(&#39;51job.csv&#39;,encoding=&#39;ANSI&#39;)</code> 写入编码格式</li>
<li><code>data.to_csv(&#39;51job.csv&#39;,encoding=&#39;utf-8&#39;)</code> 改入写编码格式</li>
<li>改写后， 只能以修改后编码格式读取，除非重新改动写入新的编码格式</li>
</ul>
</li>
<li>read_html(‘网址’)<ul>
<li>爬取网站数据<ul>
<li><code>lst = pd.read_html(&#39;http://quote.stockstar.com/stock/sha_3_1_1.html&#39;)</code></li>
</ul>
</li>
<li>写入csv<ul>
<li><code>lst[2].to_csv(&#39;gushihangqing.csv&#39;,mode=&#39;a&#39;,header=None,index=False,encoding=&#39;utf-8&#39;)</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="缺失值处理-空值"><a href="#缺失值处理-空值" class="headerlink" title="缺失值处理 (空值)"></a>缺失值处理 (空值)</h2><h3 id="删除-dropna"><a href="#删除-dropna" class="headerlink" title="删除 dropna()"></a>删除 <code>dropna()</code></h3><ul>
<li><code>data.dropna(inplace=True)</code> 删除带有Nan的整行数据 <code>inplace=True</code>修改原数据</li>
</ul>
<h3 id="填充替换-fillna"><a href="#填充替换-fillna" class="headerlink" title="填充替换 fillna()"></a>填充替换 <code>fillna()</code></h3><ul>
<li>直接替换掉 该字段所有空值<ul>
<li><code>data[&#39;某字段&#39;].fillna(&#39;要更新的值&#39;)</code></li>
</ul>
</li>
<li>用平均值替换掉 该字段所有空值 （其他值同理，如：最大值。最小值）<ul>
<li><code>data[&#39;某字段&#39;].fillna(data[&#39;某字段&#39;].mean())</code></li>
</ul>
</li>
</ul>
<h3 id="判断-isnull"><a href="#判断-isnull" class="headerlink" title="判断 isnull()"></a>判断 <code>isnull()</code></h3><ul>
<li><code>data.isnull()</code> 判断是否为空，返回 True 和 False</li>
</ul>
<h2 id="排序-sort"><a href="#排序-sort" class="headerlink" title="排序 sort"></a>排序 <code>sort</code></h2><ul>
<li><h4 id="ascending-表示升"><a href="#ascending-表示升" class="headerlink" title="ascending 表示升"></a>ascending 表示升</h4></li>
<li><h4 id="descending-表示降"><a href="#descending-表示降" class="headerlink" title="descending 表示降"></a>descending 表示降</h4></li>
<li><h4 id="注意在使用sort-index对DataFrame进行排序的时候，不能直接对index和columns都含有的字段进行排序，会报错。"><a href="#注意在使用sort-index对DataFrame进行排序的时候，不能直接对index和columns都含有的字段进行排序，会报错。" class="headerlink" title="注意在使用sort_index对DataFrame进行排序的时候，不能直接对index和columns都含有的字段进行排序，会报错。"></a>注意在使用<code>sort_index</code>对<code>DataFrame</code>进行排序的时候，不能直接对<code>index</code>和<code>columns</code>都含有的字段进行排序，会报错。</h4></li>
<li><p>直接以索引排序</p>
<ul>
<li><code>data.sort_index(axis=0,ascending=True)</code></li>
<li>参数<strong>axis</strong>只有两个值，分别是<strong>0</strong>和<strong>1</strong>，<ul>
<li>而 <strong>df中只有两个index</strong> 分别是<ul>
<li><strong>表最左一列的时间</strong> (左侧标头)</li>
<li><strong>表最上一行的ABCDE</strong> (头部标头)</li>
<li>axis=0 对应的是对左边一列的index进行排序</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><p>以某个字段的values值排序 即：按照‘列名’排序（多列可用 [‘a’,’b’…. ]），默认升序</p>
<ul>
<li><code>data.sort_values(by=&#39;某字段&#39;,ascending=False)</code></li>
<li>by 参数的作用是针对某一（些）列进行排序（不能对行使用 by 参数）</li>
</ul>
</li>
</ul>
<h2 id="loc-和-iloc"><a href="#loc-和-iloc" class="headerlink" title="loc 和 iloc"></a><code>loc</code> 和 <code>iloc</code></h2><h3 id="loc-通过行标签索引行数据"><a href="#loc-通过行标签索引行数据" class="headerlink" title="loc 通过行标签索引行数据"></a><code>loc</code> 通过行标签索引行数据</h3><ul>
<li><code>data.loc[3]</code></li>
<li><code>data.loc[:3]</code></li>
<li><code>data.loc[::2]</code></li>
</ul>
<h3 id="iloc-通过行号索引行数据"><a href="#iloc-通过行号索引行数据" class="headerlink" title="iloc 通过行号索引行数据"></a><code>iloc</code> 通过行号索引行数据</h3><ul>
<li><code>data.iloc[2]</code></li>
<li><code>data.iloc[:2]</code></li>
<li><code>data.iloc[::2]</code></li>
</ul>
<h3 id="loc-和-iloc区别"><a href="#loc-和-iloc区别" class="headerlink" title="loc 和 iloc区别"></a><code>loc</code> 和 <code>iloc</code>区别</h3><ul>
<li><h3 id="区别："><a href="#区别：" class="headerlink" title="区别："></a>区别：</h3><ul>
<li>不变动的情况，感觉没啥区别</li>
<li>但给标签改索引</li>
<li>data.index = range(10,26) # 给数据标签加索引</li>
<li>然后 就可以和感受到，差别</li>
</ul>
</li>
</ul>
<h2 id="比较"><a href="#比较" class="headerlink" title="比较"></a>比较</h2><ul>
<li>条件就是运用比较运算符比较</li>
<li>单个条件<ul>
<li><code>data[data[&#39;salary&#39;]&gt;1002]</code></li>
</ul>
</li>
<li>多个条件<ul>
<li><code>data[data[&#39;salary&#39;]&gt;1002][data[&#39;salary&#39;]&lt;1008]</code></li>
<li><code>data[(data[&#39;salary&#39;]&gt;1002)&amp;(data[&#39;salary&#39;]&lt;1008)&amp;(data[&#39;date&#39;]==&#39;4月2日&#39;)]</code></li>
</ul>
</li>
</ul>
<h2 id="替换"><a href="#替换" class="headerlink" title="替换"></a>替换</h2><ul>
<li>单个值替换单个值<ul>
<li><code>data.replace(要替换的值,更新的值)</code></li>
</ul>
</li>
<li>多个值替换单个值<ul>
<li><code>data.replace([要替换的值,要替换的值...],更新的值)</code></li>
</ul>
</li>
<li>多个值替换多个值<ul>
<li><code>data.replace([要替换的值,要替换的值...],[更新的值,更新的值...])</code></li>
</ul>
</li>
</ul>
<h2 id="数据"><a href="#数据" class="headerlink" title="数据"></a>数据</h2><ul>
<li><p>数据集</p>
</li>
<li><ul>
<li>特征</li>
<li>标签</li>
</ul>
</li>
</ul>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/01/18/scrapy爬虫框架配置-settings/">
                scrapy爬虫框架配置--settings
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-01-18</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">我们可以用一个settings.py做个简单的介绍和解析：</span><br><span class="line">例： ----&gt;</span><br><span class="line"></span><br><span class="line"># -*- coding: utf-8 -*-</span><br><span class="line"></span><br><span class="line"># Scrapy settings for xigua project</span><br><span class="line">#</span><br><span class="line"># For simplicity, this file contains only settings considered important or</span><br><span class="line"># commonly used. You can find more settings consulting the documentation:</span><br><span class="line">#</span><br><span class="line">#     https://doc.scrapy.org/en/latest/topics/settings.html</span><br><span class="line">#     https://doc.scrapy.org/en/latest/topics/downloader-middleware.html</span><br><span class="line">#     https://doc.scrapy.org/en/latest/topics/spider-middleware.html</span><br><span class="line"></span><br><span class="line">BOT_NAME = &apos;xigua&apos;    # Scrapy项目的名字,这将用来构造默认 User-Agent,同时也用来log,当您使用 startproject 命令创建项目时其也被自动赋值。</span><br><span class="line"></span><br><span class="line">SPIDER_MODULES = [&apos;xigua.spiders&apos;]　　#Scrapy搜索spider的模块列表 默认: [xxx.spiders]</span><br><span class="line">NEWSPIDER_MODULE = &apos;xigua.spiders&apos;　　#使用 genspider 命令创建新spider的模块。默认: &apos;xxx.spiders&apos;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># Crawl responsibly by identifying yourself (and your website) on the user-agent</span><br><span class="line">#爬取的默认User-Agent，除非被覆盖</span><br><span class="line">#USER_AGENT = &apos;xigua (+http://www.yourdomain.com)&apos;</span><br><span class="line"></span><br><span class="line"># Obey robots.txt rules</span><br><span class="line">#如果启用,Scrapy将会采用 robots.txt策略，常使用不遵循Flase</span><br><span class="line">ROBOTSTXT_OBEY = False</span><br><span class="line"></span><br><span class="line"># Configure maximum concurrent requests performed by Scrapy (default: 16)</span><br><span class="line">#Scrapy downloader 并发请求(concurrent requests)的最大值,默认: 16</span><br><span class="line">#CONCURRENT_REQUESTS = 32</span><br><span class="line"></span><br><span class="line"># Configure a delay for requests for the same website (default: 0)</span><br><span class="line">#未同意网站的请求配置延迟（默认为0）</span><br><span class="line"># See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay</span><br><span class="line"># See also autothrottle settings and docs</span><br><span class="line">DOWNLOAD_DELAY = 3　　# 下载器延迟时间，下载器在同一网站面前需要等待的时间，该选项可以用来限制爬取速度,减轻服务器压力。同时也支持小数:0.25 以秒为单# The download delay setting will honor only one of:</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line"># 下载延迟设置，只能有一个生效</span><br><span class="line">#CONCURRENT_REQUESTS_PER_DOMAIN = 16　　# 对单个网站进行并发请求的最大值</span><br><span class="line">#CONCURRENT_REQUESTS_PER_IP = 16　　</span><br><span class="line">#对单个ip进行并发请求的最大值，如果非0，则忽略，CONCURRENT_REQUESTS_PER_DOMAIN 设定,使用该设定。 </span><br><span class="line">#也就是说,并发限制将针对IP,而不是网站。该设定也影响 DOWNLOAD_DELAY: 如果 CONCURRENT_REQUESTS_PER_IP 非0,下载延迟应用在IP而不是网站上。</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># Disable cookies (enabled by default)</span><br><span class="line"># 禁用cookie（默认情况下启用）</span><br><span class="line">#COOKIES_ENABLED = False</span><br><span class="line"></span><br><span class="line"># Disable Telnet Console (enabled by default)</span><br><span class="line"># 禁用Telent控制台（默认启用）</span><br><span class="line">#TELNETCONSOLE_ENABLED = False</span><br><span class="line"></span><br><span class="line"># Override the default request headers:</span><br><span class="line"># 覆盖默认请求标头，也可以加入请求头，获取同样来自开发着工具，</span><br><span class="line"># 很多网站都会检查客户端的headers，比如豆瓣就是每一个请求都检查headers的user_agent，否则只会返回403，可以开启 USER_AGENT 请求头</span><br><span class="line">#DEFAULT_REQUEST_HEADERS = &#123;</span><br><span class="line">#   &apos;Accept&apos;: &apos;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&apos;,</span><br><span class="line">#   &apos;Accept-Language&apos;: &apos;en&apos;,</span><br><span class="line">#&#125;</span><br><span class="line"></span><br><span class="line"># Enable or disable spider middlewares</span><br><span class="line"># 启用或禁用蜘蛛中间件</span><br><span class="line"># See https://doc.scrapy.org/en/latest/topics/spider-middleware.html</span><br><span class="line">#SPIDER_MIDDLEWARES = &#123;</span><br><span class="line">#    &apos;xigua.middlewares.XiguaSpiderMiddleware&apos;: 543,</span><br><span class="line">#&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># Enable or disable downloader middlewares</span><br><span class="line"># 启用或禁用下载器中间件</span><br><span class="line"># See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html</span><br><span class="line">#DOWNLOADER_MIDDLEWARES = &#123;</span><br><span class="line">#    &apos;xigua.middlewares.XiguaDownloaderMiddleware&apos;: 543,</span><br><span class="line">#&#125;</span><br><span class="line"></span><br><span class="line"># Enable or disable extensions</span><br><span class="line">#启用或禁用扩展程序</span><br><span class="line"># See https://doc.scrapy.org/en/latest/topics/extensions.html</span><br><span class="line">#EXTENSIONS = &#123;</span><br><span class="line">#    &apos;scrapy.extensions.telnet.TelnetConsole&apos;: None,</span><br><span class="line">#&#125;</span><br><span class="line"></span><br><span class="line"># Configure item pipelines</span><br><span class="line"># 配置项目管道，如下载图片的图片管道，分布式爬虫多爬虫的pipeline，结尾int值是优先级，可以理解为权重，以逗号间隔，是个集合</span><br><span class="line"># See https://doc.scrapy.org/en/latest/topics/item-pipeline.html</span><br><span class="line">ITEM_PIPELINES = &#123;</span><br><span class="line">   &apos;xigua.pipelines.XiguaPipeline&apos;: 300,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"># Enable and configure the AutoThrottle extension (disabled by default)</span><br><span class="line"># 启用或配置AutoThrottle扩展（默认情况下禁用）</span><br><span class="line"># See https://doc.scrapy.org/en/latest/topics/autothrottle.html</span><br><span class="line">#AUTOTHROTTLE_ENABLED = True</span><br><span class="line"></span><br><span class="line"># The initial download delay</span><br><span class="line"># 初始下载延迟</span><br><span class="line">#AUTOTHROTTLE_START_DELAY = 5</span><br><span class="line"></span><br><span class="line"># The maximum download delay to be set in case of high latencies</span><br><span class="line"># 在高延迟的情况下设置最大下载延迟</span><br><span class="line">#AUTOTHROTTLE_MAX_DELAY = 60</span><br><span class="line"></span><br><span class="line"># The average number of requests Scrapy should be sending in parallel to each remote server</span><br><span class="line"># Scrapy请求的平均数量应该并行发送每个远程服务器</span><br><span class="line">#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0</span><br></pre></td></tr></table></figure>

<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br></pre></td><td class="code"><pre><span class="line"># Enable showing throttling stats for every response received:</span><br><span class="line"># 启用显示所收到的每个响应的调节统计信息</span><br><span class="line">#AUTOTHROTTLE_DEBUG = False</span><br><span class="line"></span><br><span class="line"># Enable and configure HTTP caching (disabled by default)</span><br><span class="line"># 启用或配置 Http 缓存（默认情况下禁用）</span><br><span class="line"># See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings</span><br><span class="line">#HTTPCACHE_ENABLED = True</span><br><span class="line">#HTTPCACHE_EXPIRATION_SECS = 0</span><br><span class="line">#HTTPCACHE_DIR = &apos;httpcache&apos;</span><br><span class="line">#HTTPCACHE_IGNORE_HTTP_CODES = []</span><br><span class="line">#HTTPCACHE_STORAGE = &apos;scrapy.extensions.httpcache.FilesystemCacheStorage&apos;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">这就是一个完整的setting.py的接本情况：</span><br><span class="line">接下来再来详细看看，并且还有哪些可以配置的呢？</span><br><span class="line">-----》</span><br><span class="line"></span><br><span class="line">#-----------------------日志文件配置-----------------------------------</span><br><span class="line"># 默认: True,是否启用logging。</span><br><span class="line"># LOG_ENABLED=True</span><br><span class="line"># 默认: &apos;utf-8&apos;,logging使用的编码。</span><br><span class="line"># LOG_ENCODING=&apos;utf-8&apos;</span><br><span class="line"># 它是利用它的日志信息可以被格式化的字符串。默认值：&apos;%(asctime)s [%(name)s] %(levelname)s: %(message)s&apos;</span><br><span class="line"># LOG_FORMAT=&apos;%(asctime)s [%(name)s] %(levelname)s: %(message)s&apos;</span><br><span class="line"># 它是利用它的日期/时间可以格式化字符串。默认值： &apos;%Y-%m-%d %H:%M:%S&apos;</span><br><span class="line"># LOG_DATEFORMAT=&apos;%Y-%m-%d %H:%M:%S&apos;</span><br><span class="line">#日志文件名</span><br><span class="line">#LOG_FILE = &quot;dg.log&quot;</span><br><span class="line">#日志文件级别,默认值：“DEBUG”,log的最低级别。可选的级别有: CRITICAL、 ERROR、WARNING、INFO、DEBUG 。</span><br><span class="line">LOG_LEVEL = &apos;WARNING&apos;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># -----------------------------robots协议---------------------------------------------</span><br><span class="line"># Obey robots.txt rules</span><br><span class="line"># robots.txt 是遵循 Robot协议 的一个文件，它保存在网站的服务器中，它的作用是，告诉搜索引擎爬虫，</span><br><span class="line"># 本网站哪些目录下的网页 不希望 你进行爬取收录。在Scrapy启动后，会在第一时间访问网站的 robots.txt 文件，</span><br><span class="line"># 然后决定该网站的爬取范围。</span><br><span class="line"># ROBOTSTXT_OBEY = True</span><br><span class="line"></span><br><span class="line"># 对于失败的HTTP请求(如超时)进行重试会降低爬取效率，当爬取目标基数很大时，舍弃部分数据不影响大局，提高效率</span><br><span class="line">RETRY_ENABLED = False</span><br><span class="line">#请求下载超时时间，默认180秒</span><br><span class="line">DOWNLOAD_TIMEOUT=20</span><br><span class="line"># 这是响应的下载器下载的最大尺寸，默认值：1073741824 (1024MB)</span><br><span class="line"># DOWNLOAD_MAXSIZE=1073741824</span><br><span class="line"># 它定义为响应下载警告的大小，默认值：33554432 (32MB)</span><br><span class="line"># DOWNLOAD_WARNSIZE=33554432</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># ------------------------全局并发数的一些配置:-------------------------------</span><br><span class="line"># Configure maximum concurrent requests performed by Scrapy (default: 16)</span><br><span class="line"># 默认 Request 并发数：16</span><br><span class="line"># CONCURRENT_REQUESTS = 32</span><br><span class="line"># 默认 Item 并发数：100</span><br><span class="line"># CONCURRENT_ITEMS = 100</span><br><span class="line"># The download delay setting will honor only one of:</span><br><span class="line"># 默认每个域名的并发数：8</span><br><span class="line">#CONCURRENT_REQUESTS_PER_DOMAIN = 16</span><br><span class="line"># 每个IP的最大并发数：0表示忽略</span><br><span class="line"># CONCURRENT_REQUESTS_PER_IP = 0</span><br><span class="line"></span><br><span class="line"># Configure a delay for requests for the same website (default: 0)</span><br><span class="line"># See http://scrapy.readthedocs.org/en/latest/topics/settings.html#download-delay</span><br><span class="line"># See also autothrottle settings and docs</span><br><span class="line">#DOWNLOAD_DELAY 会影响 CONCURRENT_REQUESTS，不能使并发显现出来,设置下载延迟</span><br><span class="line">#DOWNLOAD_DELAY = 3</span><br><span class="line"></span><br><span class="line"># Disable cookies (enabled by default)</span><br><span class="line">#禁用cookies,有些站点会从cookies中判断是否为爬虫</span><br><span class="line"># COOKIES_ENABLED = True</span><br><span class="line"># COOKIES_DEBUG = True</span><br><span class="line"></span><br><span class="line"># Crawl responsibly by identifying yourself (and your website) on the user-agent</span><br><span class="line"># 它定义了在抓取网站所使用的用户代理，默认值：“Scrapy / VERSION“</span><br><span class="line">#USER_AGENT = &apos; (+http://www.yourdomain.com)&apos;</span><br><span class="line"></span><br><span class="line"># Override the default request headers:</span><br><span class="line">DEFAULT_REQUEST_HEADERS = &#123;</span><br><span class="line">  &apos;Accept&apos;: &apos;text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&apos;,</span><br><span class="line">  &apos;Accept-Language&apos;: &apos;en&apos;,</span><br><span class="line">&#125;</span><br><span class="line"># Enable or disable spider middlewares</span><br><span class="line"># See http://scrapy.readthedocs.org/en/latest/topics/spider-middleware.html</span><br><span class="line">SPIDER_MIDDLEWARES = &#123;</span><br><span class="line">    &apos;companyNews.middlewares.UserAgentmiddleware&apos;: 401,</span><br><span class="line">    &apos;companyNews.middlewares.ProxyMiddleware&apos;:426,</span><br><span class="line">&#125;</span><br><span class="line"># Enable or disable downloader middlewares</span><br><span class="line"># See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html</span><br><span class="line">DOWNLOADER_MIDDLEWARES = &#123;</span><br><span class="line">    &apos;companyNews.middlewares.UserAgentmiddleware&apos;: 400,</span><br><span class="line">    &apos;companyNews.middlewares.ProxyMiddleware&apos;:425,</span><br><span class="line">    # &apos;scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware&apos;:423,</span><br><span class="line">     # &apos;companyNews.middlewares.CookieMiddleware&apos;: 700,</span><br><span class="line">&#125;</span><br><span class="line">MYEXT_ENABLED=True      # 开启扩展</span><br><span class="line">IDLE_NUMBER=12           # 配置空闲持续时间单位为 360个 ，一个时间单位为5s</span><br><span class="line"># Enable or disable extensions</span><br><span class="line"># See http://scrapy.readthedocs.org/en/latest/topics/extensions.html</span><br><span class="line"># 在 EXTENSIONS 配置，激活扩展</span><br><span class="line">EXTENSIONS = &#123;</span><br><span class="line">    # &apos;scrapy.extensions.telnet.TelnetConsole&apos;: None,</span><br><span class="line">    &apos;companyNews.extensions.RedisSpiderSmartIdleClosedExensions&apos;: 500,</span><br><span class="line">&#125;</span><br><span class="line"># Configure item pipelines</span><br><span class="line"># See http://scrapy.readthedocs.org/en/latest/topics/item-pipeline.html</span><br><span class="line"># 注意:自定义pipeline的优先级需高于Redispipeline,因为RedisPipeline不会返回item,</span><br><span class="line"># 所以如果RedisPipeline优先级高于自定义pipeline,那么自定义pipeline无法获取到item</span><br><span class="line">ITEM_PIPELINES = &#123;</span><br><span class="line">     #将清除的项目在redis进行处理，# 将RedisPipeline注册到pipeline组件中(这样才能将数据存入Redis)</span><br><span class="line">    # &apos;scrapy_redis.pipelines.RedisPipeline&apos;: 400,</span><br><span class="line">    &apos;companyNews.pipelines.companyNewsPipeline&apos;: 300,# 自定义pipeline视情况选择性注册(可选)</span><br><span class="line">&#125;</span><br><span class="line"># Enable and configure HTTP caching (disabled by default)</span><br><span class="line"># See http://scrapy.readthedocs.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># ----------------scrapy默认已经自带了缓存，配置如下-----------------</span><br><span class="line"># 打开缓存</span><br><span class="line">#HTTPCACHE_ENABLED = True</span><br><span class="line"># 设置缓存过期时间（单位：秒）</span><br><span class="line">#HTTPCACHE_EXPIRATION_SECS = 0</span><br><span class="line"># 缓存路径(默认为：.scrapy/httpcache)</span><br><span class="line">#HTTPCACHE_DIR = &apos;httpcache&apos;</span><br><span class="line"># 忽略的状态码</span><br><span class="line">#HTTPCACHE_IGNORE_HTTP_CODES = []</span><br><span class="line"># HTTPERROR_ALLOWED_CODES = [302, 301]</span><br><span class="line"># 缓存模式(文件缓存)</span><br><span class="line">#HTTPCACHE_STORAGE = &apos;scrapy.extensions.httpcache.FilesystemCacheStorage&apos;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#-----------------Scrapy-Redis分布式爬虫相关设置如下--------------------------</span><br><span class="line"># Enables scheduling storing requests queue in redis.</span><br><span class="line">#启用Redis调度存储请求队列，使用Scrapy-Redis的调度器,不再使用scrapy的调度器</span><br><span class="line">SCHEDULER = &quot;scrapy_redis.scheduler.Scheduler&quot;</span><br><span class="line"></span><br><span class="line"># Ensure all spiders share same duplicates filter through redis.</span><br><span class="line">#确保所有的爬虫通过Redis去重，使用Scrapy-Redis的去重组件,不再使用scrapy的去重组件</span><br><span class="line">DUPEFILTER_CLASS = &quot;scrapy_redis.dupefilter.RFPDupeFilter&quot;</span><br><span class="line"></span><br><span class="line"># 默认请求序列化使用的是pickle 但是我们可以更改为其他类似的。PS：这玩意儿2.X的可以用。3.X的不能用</span><br><span class="line"># SCHEDULER_SERIALIZER = &quot;scrapy_redis.picklecompat&quot;</span><br><span class="line"></span><br><span class="line"># 使用优先级调度请求队列 （默认使用），</span><br><span class="line"># 使用Scrapy-Redis的从请求集合中取出请求的方式,三种方式择其一即可:</span><br><span class="line"># 分别按(1)请求的优先级/(2)队列FIFO/(先进先出)(3)栈FILO 取出请求（先进后出）</span><br><span class="line"># SCHEDULER_QUEUE_CLASS = &apos;scrapy_redis.queue.PriorityQueue&apos;</span><br><span class="line"># 可选用的其它队列</span><br><span class="line">SCHEDULER_QUEUE_CLASS = &apos;scrapy_redis.queue.FifoQueue&apos;</span><br><span class="line"># SCHEDULER_QUEUE_CLASS = &apos;scrapy_redis.queue.LifoQueue&apos;</span><br><span class="line"></span><br><span class="line"># Don&apos;t cleanup redis queues, allows to pause/resume crawls.</span><br><span class="line">#不清除Redis队列、这样可以暂停/恢复 爬取，</span><br><span class="line"># 允许暂停,redis请求记录不会丢失(重启爬虫不会重头爬取已爬过的页面)</span><br><span class="line">#SCHEDULER_PERSIST = True</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#----------------------redis的地址配置-------------------------------------</span><br><span class="line"># Specify the full Redis URL for connecting (optional).</span><br><span class="line"># If set, this takes precedence over the REDIS_HOST and REDIS_PORT settings.</span><br><span class="line"># 指定用于连接redis的URL（可选）</span><br><span class="line"># 如果设置此项，则此项优先级高于设置的REDIS_HOST 和 REDIS_PORT</span><br><span class="line"># REDIS_URL = &apos;redis://root:密码@主机ＩＰ:端口&apos;</span><br><span class="line"># REDIS_URL = &apos;redis://root:123456@192.168.8.30:6379&apos;</span><br><span class="line">REDIS_URL = &apos;redis://root:%s@%s:%s&apos;%(password_redis,host_redis,port_redis)</span><br><span class="line"># 自定义的redis参数（连接超时之类的）</span><br><span class="line">REDIS_PARAMS=&#123;&apos;db&apos;: db_redis&#125;</span><br><span class="line"># Specify the host and port to use when connecting to Redis (optional).</span><br><span class="line"># 指定连接到redis时使用的端口和地址（可选）</span><br><span class="line">#REDIS_HOST = &apos;127.0.0.1&apos;</span><br><span class="line">#REDIS_PORT = 6379</span><br><span class="line">#REDIS_PASS = &apos;19940225&apos;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">#-----------------------------------------暂时用不到-------------------------------------------------------</span><br><span class="line"># 它定义了将被允许抓取的网址的长度为URL的最大极限，默认值：2083</span><br><span class="line"># URLLENGTH_LIMIT=2083</span><br><span class="line"># 爬取网站最大允许的深度(depth)值,默认值0。如果为0，则没有限制</span><br><span class="line"># DEPTH_LIMIT = 3</span><br><span class="line"># 整数值。用于根据深度调整request优先级。如果为0，则不根据深度进行优先级调整。</span><br><span class="line"># DEPTH_PRIORITY=3</span><br><span class="line"></span><br><span class="line"># 最大空闲时间防止分布式爬虫因为等待而关闭</span><br><span class="line"># 这只有当上面设置的队列类是SpiderQueue或SpiderStack时才有效</span><br><span class="line"># 并且当您的蜘蛛首次启动时，也可能会阻止同一时间启动（由于队列为空）</span><br><span class="line"># SCHEDULER_IDLE_BEFORE_CLOSE = 10</span><br><span class="line"></span><br><span class="line"># 序列化项目管道作为redis Key存储</span><br><span class="line"># REDIS_ITEMS_KEY = &apos;%(spider)s:items&apos;</span><br><span class="line"></span><br><span class="line"># 默认使用ScrapyJSONEncoder进行项目序列化</span><br><span class="line"># You can use any importable path to a callable object.</span><br><span class="line"># REDIS_ITEMS_SERIALIZER = &apos;json.dumps&apos;</span><br><span class="line"></span><br><span class="line"># 自定义redis客户端类</span><br><span class="line"># REDIS_PARAMS[&apos;redis_cls&apos;] = &apos;myproject.RedisClient&apos;</span><br><span class="line"></span><br><span class="line"># 如果为True，则使用redis的&apos;spop&apos;进行操作。</span><br><span class="line"># 如果需要避免起始网址列表出现重复，这个选项非常有用。开启此选项urls必须通过sadd添加，否则会出现类型错误。</span><br><span class="line"># REDIS_START_URLS_AS_SET = False</span><br><span class="line"></span><br><span class="line"># RedisSpider和RedisCrawlSpider默认 start_usls 键</span><br><span class="line"># REDIS_START_URLS_KEY = &apos;%(name)s:start_urls&apos;</span><br><span class="line"></span><br><span class="line"># 设置redis使用utf-8之外的编码</span><br><span class="line"># REDIS_ENCODING = &apos;latin1&apos;</span><br><span class="line"></span><br><span class="line"># Disable Telnet Console (enabled by default)</span><br><span class="line"># 它定义是否启用telnetconsole,默认值：True</span><br><span class="line">#TELNETCONSOLE_ENABLED = False</span><br><span class="line"></span><br><span class="line"># Enable and configure the AutoThrottle extension (disabled by default)</span><br><span class="line"># See http://doc.scrapy.org/en/latest/topics/autothrottle.html</span><br><span class="line">#AUTOTHROTTLE_ENABLED = True</span><br><span class="line"># The initial download delay</span><br><span class="line"># 开始下载时限速并延迟时间</span><br><span class="line">#AUTOTHROTTLE_START_DELAY = 5</span><br><span class="line"># The maximum download delay to be set in case of high latencies</span><br><span class="line">#高并发请求时最大延迟时间</span><br><span class="line">#AUTOTHROTTLE_MAX_DELAY = 60</span><br><span class="line"># The average number of requests Scrapy should be sending in parallel to</span><br><span class="line"># each remote server</span><br><span class="line">#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0</span><br><span class="line"># Enable showing throttling stats for every response received:</span><br><span class="line">#AUTOTHROTTLE_DEBUG = False</span><br><span class="line"></span><br><span class="line">最后再来两条启用调试的命令：</span><br><span class="line">启用调试工具</span><br><span class="line">命令行调试</span><br><span class="line">scrapy shell url 查看网页，不过这种方式可能对于要请求头的网页不行，对于一般的网页还是可以的</span><br><span class="line">scrapy view shell 用来查看动态加载的网页，如果查看的网页用了动态加载，那么用这个命令行打开的网页就是不完整的，肯定缺少了什么</span><br></pre></td></tr></table></figure>

<p>暂停和恢复爬虫<br>初学者最头疼的事情就是没有处理好异常，当爬虫爬到一半的时候突然因为错误而中断了，但是这时又不能从中断的地方开始继续爬，顿时感觉心里日了狗，但是这里有一个方法可以暂时的存储你爬的状态，当爬虫中断的时候继续打开后依然可以从中断的地方爬，不过虽说持久化可以有效的处理，但是要注意的是当使用cookie临时的模拟登录状态的时候要注意cookie的有效期</p>
<p>只需要在setting.py中JOB_DIR=file_name 其中填的是你的文件目录，注意这里的目录不允许共享，只能存储单独的一个spdire的运行状态，如果你不想在从中断的地方开始运行，只需要将这个文件夹删除即可</p>
<p>当然还有其他的放法：scrapy crawl somespider -s JOBDIR=crawls/somespider-1，这个是在终端启动爬虫的时候调用的，可以通过ctr+c中断，恢复还是输入上面的命令</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2019/01/12/redis-数据操作/">
                redis-数据操作
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2019-01-12</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h1 id="redis"><a href="#redis" class="headerlink" title="redis"></a><code>redis</code></h1><ul>
<li><h3 id="定义："><a href="#定义：" class="headerlink" title="定义："></a>定义：</h3><ul>
<li><code>redis</code>是开源的，内存数据库，可以用于数据库缓存和消息中间件，支持多种数据类型，字符串，哈希，列表，集合，有序集合等</li>
</ul>
</li>
</ul>
<h3 id="本地启动-常用命令"><a href="#本地启动-常用命令" class="headerlink" title="本地启动 - 常用命令"></a>本地启动 - 常用命令</h3><ul>
<li><code>redis-cli</code></li>
<li><code>redis-server.exe</code> # 带样式 前提你装了</li>
<li><code>/etc/init.d/redis-server stop</code> —&gt; 停止</li>
<li><code>/etc/init.d/redis-server start</code> —&gt; 启动</li>
<li><code>/etc/init.d/redis-server restart</code> —&gt; 重启</li>
</ul>
<h2 id="远程连接redis数据库"><a href="#远程连接redis数据库" class="headerlink" title="远程连接redis数据库"></a>远程连接<code>redis</code>数据库</h2><ul>
<li><code>redis-cli -h &lt;hostname&gt; -p &lt;port&gt;</code></li>
</ul>
<h3 id="数据库切换"><a href="#数据库切换" class="headerlink" title="数据库切换"></a>数据库切换</h3><ul>
<li><code>select 数据库名</code> 注：几号数据库或是新建的数据库名</li>
</ul>
<h3 id="通过key查询值"><a href="#通过key查询值" class="headerlink" title="通过key查询值"></a>通过key查询值</h3><ul>
<li>通过所key查询所有值<ul>
<li>查询所有键<ul>
<li><code>keys *</code></li>
</ul>
</li>
<li>查询包含a的键<ul>
<li><code>keys &#39;a*&#39;</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="查看键对应的value值的类型"><a href="#查看键对应的value值的类型" class="headerlink" title="查看键对应的value值的类型"></a>查看键对应的value值的类型</h3><ul>
<li><code>type key</code></li>
</ul>
<h3 id="值的类型"><a href="#值的类型" class="headerlink" title="值的类型"></a>值的类型</h3><ul>
<li>字符串 <code>string</code></li>
<li>哈希 <code>hash</code></li>
<li>列表 <code>list</code></li>
<li>集合 <code>set</code></li>
<li>有序集合 <code>zset</code></li>
</ul>
<h2 id="string"><a href="#string" class="headerlink" title="string"></a>string</h2><h3 id="保存设置键值"><a href="#保存设置键值" class="headerlink" title="保存设置键值"></a>保存设置键值</h3><ul>
<li>设置的值不存在就添加，存在则修改<ul>
<li><code>set key value</code></li>
</ul>
</li>
</ul>
<h4 id="设置键值及过期时间，单位秒"><a href="#设置键值及过期时间，单位秒" class="headerlink" title="设置键值及过期时间，单位秒"></a>设置键值及过期时间，单位秒</h4><ul>
<li><code>setex key 秒数 value</code></li>
</ul>
<h4 id="设置多个键值"><a href="#设置多个键值" class="headerlink" title="设置多个键值"></a>设置多个键值</h4><ul>
<li><code>mset key1 value1 key2 value2 ...</code></li>
</ul>
<h4 id="追加值"><a href="#追加值" class="headerlink" title="追加值"></a>追加值</h4><ul>
<li>append ‘key’ ‘value’<ul>
<li>理解为常用append尾部追加</li>
</ul>
</li>
</ul>
<h3 id="获取值"><a href="#获取值" class="headerlink" title="获取值"></a>获取值</h3><h4 id="通过单个key获取值"><a href="#通过单个key获取值" class="headerlink" title="通过单个key获取值"></a>通过单个key获取值</h4><ul>
<li><code>get key</code></li>
</ul>
<h4 id="通过多个key获取多个值"><a href="#通过多个key获取多个值" class="headerlink" title="通过多个key获取多个值"></a>通过多个key获取多个值</h4><ul>
<li><code>mget key1 key2...</code></li>
</ul>
<h4 id="判断键是否存在"><a href="#判断键是否存在" class="headerlink" title="判断键是否存在"></a>判断键是否存在</h4><ul>
<li>如果存在返回1，不存在返回0<ul>
<li><code>exists key1</code></li>
</ul>
</li>
</ul>
<h3 id="删除"><a href="#删除" class="headerlink" title="删除"></a>删除</h3><h4 id="删除键及对应的值"><a href="#删除键及对应的值" class="headerlink" title="删除键及对应的值"></a>删除键及对应的值</h4><ul>
<li><code>del key1 key2...</code><ul>
<li>可单个，可多个</li>
</ul>
</li>
</ul>
<h4 id="设置key的过期时间，单位秒"><a href="#设置key的过期时间，单位秒" class="headerlink" title="设置key的过期时间，单位秒"></a>设置key的过期时间，单位秒</h4><ul>
<li><code>expire &#39;key&#39; 秒数</code></li>
</ul>
<h4 id="查看有效时间，单位秒"><a href="#查看有效时间，单位秒" class="headerlink" title="查看有效时间，单位秒"></a>查看有效时间，单位秒</h4><ul>
<li><code>ttl key</code></li>
</ul>
<h2 id="hash"><a href="#hash" class="headerlink" title="hash"></a>hash</h2><ul>
<li>用于存储对象，对象的结构为属性、值+</li>
<li>值的类型为string</li>
</ul>
<h3 id="保存设置属性"><a href="#保存设置属性" class="headerlink" title="保存设置属性"></a>保存设置属性</h3><h4 id="设置单个属性"><a href="#设置单个属性" class="headerlink" title="设置单个属性"></a>设置单个属性</h4><ul>
<li><code>hset key field value</code><ul>
<li>key的属性field为value</li>
<li>个人理解：字典的值是另一个字典</li>
</ul>
</li>
</ul>
<h4 id="设置多个属性"><a href="#设置多个属性" class="headerlink" title="设置多个属性"></a>设置多个属性</h4><ul>
<li><code>hmset key field1 value1 field2 value2 ...</code></li>
</ul>
<h3 id="获取"><a href="#获取" class="headerlink" title="获取"></a>获取</h3><h4 id="获取指定键所有的属性"><a href="#获取指定键所有的属性" class="headerlink" title="获取指定键所有的属性"></a>获取指定键所有的属性</h4><ul>
<li><code>hkeys key</code></li>
</ul>
<p>获取指定属性的值</p>
<ul>
<li><code>hget key field</code></li>
</ul>
<h4 id="获取指定属性的多个值"><a href="#获取指定属性的多个值" class="headerlink" title="获取指定属性的多个值"></a>获取指定属性的多个值</h4><ul>
<li><code>hmget key field1 field2 ...</code></li>
</ul>
<h4 id="获取key的所有属性"><a href="#获取key的所有属性" class="headerlink" title="获取key的所有属性"></a>获取key的所有属性</h4><ul>
<li><code>hvals key</code></li>
</ul>
<h3 id="删除-1"><a href="#删除-1" class="headerlink" title="删除"></a>删除</h3><ul>
<li>删除整个hash键及值 ， 使用del命令</li>
<li>删除属性，属性对应的值会被一起删除<ul>
<li><code>hdel key field1 field2 ...</code></li>
</ul>
</li>
</ul>
<h2 id="list"><a href="#list" class="headerlink" title="list"></a>list</h2><ul>
<li>列表的元素数据类型string</li>
<li>按插入数据顺序排序</li>
</ul>
<h3 id="增加"><a href="#增加" class="headerlink" title="增加"></a>增加</h3><h4 id="从左侧插入数据"><a href="#从左侧插入数据" class="headerlink" title="从左侧插入数据"></a>从左侧插入数据</h4><ul>
<li><code>lpush key value1 value2 ...</code></li>
</ul>
<h4 id="从右侧插入数据"><a href="#从右侧插入数据" class="headerlink" title="从右侧插入数据"></a>从右侧插入数据</h4><ul>
<li><code>rpush key value1 value2 ...</code></li>
</ul>
<h5 id="左右侧数据插入理解："><a href="#左右侧数据插入理解：" class="headerlink" title="左右侧数据插入理解："></a>左右侧数据插入理解：</h5><ul>
<li>添加完第一个值，在第一个值左侧或右侧向外添加数据元素</li>
</ul>
<h4 id="在指定元素的前或后插入新元素"><a href="#在指定元素的前或后插入新元素" class="headerlink" title="在指定元素的前或后插入新元素"></a>在指定元素的前或后插入新元素</h4><ul>
<li><p><code>linsert key before或after 现有元素 新元素</code></p>
<ul>
<li><code>linsert key before 目标元素 新添元素</code><ul>
<li>在目标元素之前添加 新元素</li>
</ul>
</li>
<li><code>linsert key after 目标元素 新添元素</code><ul>
<li>在目标元素之后添加 新元素</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="获取-1"><a href="#获取-1" class="headerlink" title="获取"></a>获取</h3><h4 id="遍历打印该key的所有值"><a href="#遍历打印该key的所有值" class="headerlink" title="遍历打印该key的所有值"></a>遍历打印该key的所有值</h4><ul>
<li><code>lrange key</code><ul>
<li><code>lrange key 起始下标 结束下标</code><ul>
<li>设置的下标区间 包含该下标 左闭右闭</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="设置指定索引位置的元素值"><a href="#设置指定索引位置的元素值" class="headerlink" title="设置指定索引位置的元素值"></a>设置指定索引位置的元素值</h4><ul>
<li><code>lset key index value</code><ul>
<li>例：<code>lset a 1 z</code><ul>
<li>修改key为a的下标为1的元素值为z</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="删除-2"><a href="#删除-2" class="headerlink" title="删除"></a>删除</h3><h4 id="删除指定元素"><a href="#删除指定元素" class="headerlink" title="删除指定元素"></a>删除指定元素</h4><ul>
<li><code>lren key count value</code><ul>
<li>count&gt;0 从头往尾移除</li>
<li>count&lt;0 从尾往头移除</li>
<li>count=0 移除所有</li>
</ul>
</li>
</ul>
<h2 id="set-amp-zset"><a href="#set-amp-zset" class="headerlink" title="set &amp; zset"></a><code>set &amp; zset</code></h2><h3 id="set"><a href="#set" class="headerlink" title="set"></a>set</h3><ul>
<li>无序集合</li>
<li>元素为string类型</li>
<li>元素具有唯一性，不重复 去重</li>
<li>对于集合没有修改操作</li>
</ul>
<h3 id="增加-1"><a href="#增加-1" class="headerlink" title="增加"></a>增加</h3><h4 id="添加元素"><a href="#添加元素" class="headerlink" title="添加元素"></a>添加元素</h4><ul>
<li><code>sadd key member1 member2 ...</code></li>
<li><code>sadd key 元素1 元素2 ...</code></li>
</ul>
<h3 id="获取集合所有元素"><a href="#获取集合所有元素" class="headerlink" title="获取集合所有元素"></a>获取集合所有元素</h3><ul>
<li><code>smembers key</code></li>
</ul>
<h3 id="删除-3"><a href="#删除-3" class="headerlink" title="删除"></a>删除</h3><h4 id="删除指定元素-1"><a href="#删除指定元素-1" class="headerlink" title="删除指定元素"></a>删除指定元素</h4><ul>
<li><code>srem key member1 member2 ...</code><ul>
<li>删除指定key的单个或多个元素</li>
</ul>
</li>
</ul>
<h2 id="zset"><a href="#zset" class="headerlink" title="zset"></a><code>zset</code></h2><ul>
<li>sorted set 有序集合</li>
<li>元素为string类型</li>
<li>元素具有唯一性，不重复 去重</li>
<li>每个元素都会关联一个double类型的score，表示权重</li>
<li>注：没有修改操作</li>
</ul>
<h3 id="增加-2"><a href="#增加-2" class="headerlink" title="增加"></a>增加</h3><h4 id="添加元素-1"><a href="#添加元素-1" class="headerlink" title="添加元素"></a>添加元素</h4><ul>
<li><code>zadd key score1 member1 score2 member2 ...</code><ul>
<li>score 值为权重(可以理解为排序的正向顺序，数值从小到大)</li>
<li>member1 值为元素 string 类型</li>
</ul>
</li>
</ul>
<h3 id="获取-2"><a href="#获取-2" class="headerlink" title="获取"></a>获取</h3><h4 id="获取指定范围内的元素（下标，左闭右闭）"><a href="#获取指定范围内的元素（下标，左闭右闭）" class="headerlink" title="获取指定范围内的元素（下标，左闭右闭）"></a>获取指定范围内的元素（下标，左闭右闭）</h4><ul>
<li><code>zrange key 起始下标 结尾下标</code></li>
</ul>
<h4 id="获取score值在min和max之间的元素"><a href="#获取score值在min和max之间的元素" class="headerlink" title="获取score值在min和max之间的元素"></a>获取score值在min和max之间的元素</h4><ul>
<li><code>zrangebyscore key min max</code><ul>
<li>min 和 max 值取决于score值</li>
</ul>
</li>
</ul>
<h4 id="获取元素member的score值"><a href="#获取元素member的score值" class="headerlink" title="获取元素member的score值"></a>获取元素member的score值</h4><ul>
<li><code>zscore key member</code><ul>
<li>score 值 可以称为 权值</li>
</ul>
</li>
</ul>
<h3 id="删除-4"><a href="#删除-4" class="headerlink" title="删除"></a>删除</h3><h4 id="删除指定元素-2"><a href="#删除指定元素-2" class="headerlink" title="删除指定元素"></a>删除指定元素</h4><ul>
<li><code>zrem key memeber1 member2 ...</code></li>
</ul>
<h4 id="删除权重值在指定范围内的元素"><a href="#删除权重值在指定范围内的元素" class="headerlink" title="删除权重值在指定范围内的元素"></a>删除权重值在指定范围内的元素</h4><ul>
<li><code>zremrangebyscore key min max</code></li>
</ul>
<h2 id="事务"><a href="#事务" class="headerlink" title="事务"></a>事务</h2><ul>
<li>命令及描述：</li>
<li>1<a href="https://www.runoob.com/redis/transactions-discard.html" target="_blank" rel="noopener">DISCARD</a>  取消事务，放弃执行事务块内的所有命令。</li>
<li>2<a href="https://www.runoob.com/redis/transactions-exec.html" target="_blank" rel="noopener">EXEC</a>  执行所有事务块内的命令。</li>
<li>3<a href="https://www.runoob.com/redis/transactions-multi.html" target="_blank" rel="noopener">MULTI</a>  标记一个事务块的开始。</li>
<li>4<a href="https://www.runoob.com/redis/transactions-unwatch.html" target="_blank" rel="noopener">UNWATCH</a>  取消 WATCH 命令对所有 key 的监视。</li>
<li>5<a href="https://www.runoob.com/redis/transactions-watch.html" target="_blank" rel="noopener">WATCH key [key …]</a>  监视一个(或多个) key ，如果在事务执行之前这个(或这些) key 被其他命令所改动，那么事务将被打断。</li>
</ul>
<h3 id="Redis-事务"><a href="#Redis-事务" class="headerlink" title="Redis 事务"></a>Redis 事务</h3><ul>
<li><p>可以一次执行多个命令， 并且带有以下两个重要的保证：</p>
</li>
<li><p>批量操作在发送 EXEC 命令前被放入队列缓存。</p>
</li>
<li><p>收到 EXEC 命令后进入事务执行，事务中任意命令执行失败，其余的命令依然被执行。</p>
</li>
<li><p>在事务执行过程，其他客户端提交的命令请求不会插入到事务执行命令序列中。</p>
</li>
</ul>
<p>一个事务从开始到执行会经历以下三个阶段：</p>
<ul>
<li>开始事务。</li>
<li>命令入队。</li>
<li>执行事务。</li>
</ul>
<h3 id="实例："><a href="#实例：" class="headerlink" title="实例："></a>实例：</h3><p>redis 127.0.0.1:6379&gt; MULTI<br>OK</p>
<p>redis 127.0.0.1:6379&gt; SET book-name “Mastering C++ in 21 days”<br>QUEUED</p>
<p>redis 127.0.0.1:6379&gt; GET book-name<br>QUEUED</p>
<p>redis 127.0.0.1:6379&gt; SADD tag “C++” “Programming” “Mastering Series”<br>QUEUED</p>
<p>redis 127.0.0.1:6379&gt; SMEMBERS tag<br>QUEUED</p>
<p>redis 127.0.0.1:6379&gt; EXEC<br>1) OK<br>2) “Mastering C++ in 21 days”<br>3) (integer) 3<br>4) 1) “Mastering Series”<br>2) “C++”<br>3) “Programming”</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2018/12/12/mysql忘记密码解决方法/">
                MySQL忘记密码解决方法
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2018-12-12</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>1，首先停止MYSQL服务，CMD打开DOS窗口，输入 net stop mysql 2，然后在CMD命令行窗口，进入MYSQL安装目录 比如E:\Program Files\MySQL\MySQL Server 5.0\bin 示范命令: 输入 e:回车, 输入cd “E:\Program Files\MySQL\MySQL Server 5.0\bin” 注意双引号也要输入,这样就可以进入Mysql安装目录了. 3，进入mysql安全模式，即当mysql起来后，不用输入密码就能进入数据库。 命令为： mysqld -nt –skip-grant-tables (注意-nt前面的空格!) 4，重新打开一个CMD命令行窗口，输入mysql -u root -p，使用空密码的方式登录MySQL（不用输入密码，直接按回车） 5，输入以下命令开始修改root用户的密码（注意：命令中mysql.user中间有个“点”） mysql&gt; update mysql.user set password=PASSWORD(‘新密码’) where User=’root’; 6，刷新权限表 mysql&gt; flush privileges; 7，退出 mysql&gt; quit 这样MYSQL超级管理员账号 ROOT已经重新设置好了，白话点讲就是利用mysql的安全模式置空模式，然后重新设定密码， 接下来 在任务管理器里结束掉 mysql-nt.exe 这个进程，重新启动MYSQL即可！（也可以在任务管理器直接重新启动服务器） MYSQL重新启动后，就可以用新设置的ROOT密码登陆MYSQL了！ </p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2018/11/12/Mysql-命令手记/">
                Mysql-命令手记
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2018-11-12</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <p>MYSQL常用命令：</p>
<p>数据备份与还原<br>·注意：不要打分号，不登陆mysql 直接在cmd下运行</p>
<p>1、备份：<br>·mysqldump -uroot -p123 要备份的数据库名&gt;生成的脚本路径</p>
<p>2、恢复：<br>·source 脚本文件路径</p>
<p>·端口号为：3306</p>
<p>·默认存储引擎：innodb</p>
<p>·默认字符集：utf-8</p>
<p>MYSQL开启关闭及查询时间版本指令：</p>
<p>·开启MySQL服务            net start mysql 或  sudo service mysql start</p>
<p>·重启服务                sudo service mysql restart</p>
<p>·查看看进程中是否存在mysql服务 ps ajx|grep mysql</p>
<p>·进入mysql数据库控制台命令：      mysql -u用户名 -p密码</p>
<p>·查看版本命令：    select version();</p>
<p>·显示当前时间命令：     select now();</p>
<p>·退出MySQL命令：      quit或exit</p>
<p>·结束MySQL服务            net stop mysql 或  sudo service mysql stop</p>
<p>修改用户名及密码相关指令：<br>·1、修改密码格式命令：         set password for 用户名@localhost = password(‘新密码’); </p>
<p>·2、修改密码格式命令：        mysqladmin -u用户名 -p旧密码 password 新密码；</p>
<p>·修改用户名命令：<br>  进入mysql库：        use mysql;<br>  然后输入：    update user set user =’新用户名’ where user =’旧用户名’；</p>
<p>创建库的相关指令：<br>·创建数据库命令：     create database 数据库名 charset=utf8;</p>
<p>·显示所有的数据库：       show databases；</p>
<p>·删除数据库命令：     drop database 数据库名；</p>
<p>·导入（连接）数据库命令：        use 数据库名</p>
<p>·查看当前使用的数据库命令：        select database();</p>
<p>·当前数据库包含的表信息命令：     show tables;</p>
<p>show create table 表名;      展示详细属性 </p>
<p>建表相关指令：<br>·创建表命令：        create table 表名 ((字段名 类型 属性)，(字段名 类型 属性));</p>
<p>·修改表名：          alter table 表名 rename to 新表名；</p>
<p>·获取表结构命令：    desc 表名；   或者   show columns from 表名；</p>
<p>·删除表命令：        drop table 表名；</p>
<p>·修改字段命令：      alter table 表名 change 原字段名 新字段名 数据类型;</p>
<p>·修改数据类型命令：        alter table 表名 modify 字段名 新数据类型;</p>
<p>·删除一个字段命令：        alter table 表名 drop 字段名;</p>
<p>·将字段1放在字段2后面命令：        alter table 表名 modify 字段名1 数据类型 after 字段名2；</p>
<p>插入数据相关命令：<br>·插入数据命令：        insert into 表名 values (添加的数据,)    #按列表竖列类型添加以，分隔<br>            insert into 表名 (字段,字段) values (添加的数据,)<br>·查看表中所有数据命令：    select * from 表名;</p>
<p>·查看相关类型数据命令：       select 字段,字段 from 表名;</p>
<p>·查询指定字段命令：        select 字段 from 表名;</p>
<p>·查询前几行数据命令：        如：查看表中前行数据       select * from 表名 limit 0,2;</p>
<p>·插入数据类型命令：         alter table 表名 add 字段 数据类型;</p>
<p>·清空表内数据命令：        delete from 表名;</p>
<p>·清空表 自增id，下次从1开始        truncate table 表名;</p>
<p>·第二种<br>（注意：这个是你通过delete from table 之后 设置的。不然不起作用） </p>
<p>如果表中的数据还有用，那么需要从特定的某一个值开始自动增长的话，做法如下<br>比如你想让id从2开始自动增长，sql如下 </p>
<p>alter table jx_pcmx AUTO_INCREMENT 2; </p>
<p>alter table jx_pcmx AUTO_INCREMENT 此处写你想让id从几开始增长的数字；</p>
<p>·删除表中数据命令：       如：删除表中编号为1的记录    delete from 表名 where id=1;  </p>
<p>·修改表中数据命令：      update 表名 set 字段=新值 where条件     如：update 表名 set name=’Mary’where id=1;</p>
<p>·在表中增加字段命令： alter table 表名 add字段 类型 其他;<br>—例如：在表MyClass中添加了一个字段passtest，类型为int(4)，默认值为空<br>   mysql&gt; alter table MyClass add passtest int(4) default ‘’;</p>
<p>·选取字段插入多条记录命令：    insert into 表名(字段名1，字段名2,….） values(值1,值2,…),(值1,值2,…)…; </p>
<p>·全部字段插入多条记录命令：    insert into 表名 values(值1，值2,…),(值1，值2,…)…;</p>
<p>·使用as 给字段起别名命令：    select 原字段名 as 新字段名 from 表名;  查询出来的结果字段名不是原字段名，变成了新字段名</p>
<p>·使用distinct可以消除重复数据        select distinct 字段名,distince 字段名 from student; 查询出来的性别（字段名）和年龄（字段名）没有重复的数据</p>
<p> MySQL支持多种类型 大致可以分为三类：数值、日期/时间 和 字符串(字符)类型。</p>
<p>常用字段类型：<br>·整形：</p>
<ul>
<li><p>tinyint(m)      1个字节 范围（-128···127）</p>
<p> int(m)       4个字节 范围（-2147483648···2147483647）</p>
<p>  bigint(m）      8个字节 范围 （+-9.22*10的18次方）</p>
</li>
</ul>
<p>·浮点型：     # 一般应用于身高体重之类</p>
<ul>
<li><p>float(m,d)      单精度浮点型 8位精度（4字节） m总个数， d小位数 </p>
<p> double(m,d)      双精度浮点型 16位精度（8字节） m总个数， d小位数 </p>
</li>
</ul>
<p>·定点数      # 精确值 一般应用于与钱相关之类的</p>
<ul>
<li>decimal(m,d)      参数 m &lt; 65 是总个数，d&lt;30 且 d&lt;m 是小位数</li>
</ul>
<p>·字符串：</p>
<ul>
<li><p>chr(n)       固定长度 最多255个字符   # 查询速度快，但占固定内存，空间消耗大</p>
<p> varchar(n)      不固定长度 最多65535个字符    #占用内存灵活，节省空间，但查询速度慢</p>
<p>  text           可变长度，最多65535个字符   # 不确定长度时使用</p>
</li>
<li><p>小总结：<br> char比varchar查询更快<br>  varchar比char占用资源少<br>  char是定长，最多255<br>  varchar是不定长，最多65535<br>  char(n)若存入字符数小于n,则以空格补于其后，查询之时再将空格去掉，所以char类型存储的字符串末尾不能有空格，varchar不限于此。<br>  char(n)固定长度，char(4)不管是存入几个字符，都将占用4个字节，varchar是存入的实际字符数+1个字节（n&lt;=255)或两个字节(n&gt;255),所以varchar(4)存入3个字符都将占用4个字节<br>  decimal(m,n)非常精确的小数</p>
</li>
</ul>
<p>时间/日期类型：<br>·date                日期  如：’2018-12-5’</p>
<p>·time                时间 如：’12:33:55’</p>
<p>·datetime            日期时间   如:’2018-12-2 22:06:44’</p>
<p>·timestamp            自动存储记录修改时间</p>
<p>数据类型的属性：<br>·null                 数据可包含null值</p>
<p>·not null             数据不可包含null值</p>
<p>·default            默认值</p>
<p>·primary key            主键</p>
<p>·auto_increment        自动递增，适用于整数类型</p>
<p>·unsigned            无符号</p>
<p>·character set         指定一个字符集<br>  name</p>
<p>·bit                称为位数据类型 0是假 1是真 作为逻辑变量使用，用来表示真、假或是、否等二值选择</p>
<p>常用权限的解释：<br>·file            在MySQL服务器上读写文件。</p>
<p>·process        显示或杀死属于其它用户的服务线程。</p>
<p>·reload        重载访问控制表，刷新日志等。</p>
<p>·shutdown        关闭MySQL服务</p>
<p>数据库/数据表/数据列权限：<br>·alter         修改已存在的数据表(例如增加/删除列)和索引。</p>
<p>·create        建立新的数据库或数据表。</p>
<p>·delete        删除表的记录。</p>
<p>·drop            删除数据库或数据表</p>
<p>·index            建立或删除索引</p>
<p>·insert        增加表的记录</p>
<p>·select        显示/搜索表的记录</p>
<p>·update        修改表中已存在的记录</p>
<p>·enum            枚举类型</p>
<p>特别的权限：<br>·all            允许做任何事（和root一样）</p>
<p>·usage            只允许登录–其它什么也不允许做。</p>
<p>条件查询：<br> 使用where子句对表中的数据筛选，结果为true的行会出现在结果集中<br> where后面支持多种运算符，进行条件的处理</p>
<p>·比较运算符：  &gt;    &lt;   &lt;=     &gt;=     =   !=    is<br>        select * from 表名 where 条件;</p>
<p>·逻辑运算符：and   or   not<br>        select * from 表名 where 条件;</p>
<p>·范围查询    between…and…<br>例：      （左闭右闭，左右都包含）<br>    select 字段 from 表名 where 字段 between 开始区间 and 结束区间；</p>
<p>·模糊查询    like     %表示任意多个任意字符    <em>表示一个任意字符<br> 例：        %  和 _ 可以加在任意位置、<br>    select * from 表名 where 字段 like ‘字符元素%’;<br>    select * from 表名 where 字段 like ‘%字符元素’;<br>    select * from 表名 where 字段 like ‘字符元素</em>‘;<br>    select * from 表名 where 字段 like ‘_字符元素’;</p>
<p>·判非空    is not null<br>例：    select * from 表名 where  字段 is not null;</p>
<p>优先级：<br>优先级由高到低的顺序为：小括号，not，比较运算符，逻辑运算符<br>and比or先运算，如果同时出现并希望先算or，需要结合()使用</p>
<p>·排序：    默认升序            升序|降序<br>  语法：    select * from 表名 order by 字段名 asc|desc </p>
<p>说明：<br>将行数据按照列1进行排序，如果某些行列1的值相同时，则按照列2排序，以此类推<br>默认按照列值从小到大排列（asc）<br>asc从小到大排列，即升序<br>desc从大到小排序，即降序<br>多次排序优先执行前面的命令</p>
<p>聚合函数：<br>·总数：    count(<em>) 表示计算总行数，括号中写星与列名，结果是相同的<br>    select count(</em>) from 表名;</p>
<p>·最大值：    max(字段名) 表示求此列的最大值<br>    select max(字段名) from 表名;  或 select max(字段名1) from 表名 where 字段名2=定值;</p>
<p>·最小值：    min(字段名) 表示求此列的最小值<br>    select min(字段名) from 表名;  或 select min(字段名1) from 表名 where 字段名2=定值;</p>
<p>·求和：    sum(字段名)表示求此列的和<br>    select sum(字段名) from 表名;  或 select sum(字段名1) from 表名 where 字段名2=定值;</p>
<p>·平均值：    avg(字段名)表示求此列的平均值<br>    select avg(字段名) from 表名;  或 select avg(字段名1) from 表名 where 字段名2=定值 and 字段名3=定值;</p>
<p>·分组：    group by<br>    select 字段名1 from 表名 group by 字段名1;  或 select avg(字段名1) from 表名 where 字段名2=定值 and 字段名3=定值;<br>说明：<br>       group by的含义:将查询结果按照1个或多个字段进行分组，字段值相同的为一组<br>       group by可用于单个字段分组，也可用于多个字段分组</p>
<p>这些还可以这么用：<br>· 语法注意：  select @1,字段1 from 表名 group by 字段1<br>    或 select 字段1,@1 from 表名 where 条件 group by 字段1;<br>          @1  —  位置只能放聚合函数、group_concat和分组的字段</p>
<p>·统计分组：<br>例：     select avg(字段名1),字段名2 from 表名 group by 字段名2;<br>例：     select count(字段名1),字段名2 from 表名 group by 字段名2;</p>
<p>·嵌套查询：<br>例：     select *from 表名 where 字段名1=(select min(字段名1) from 表名);</p>
<p>·group by + group_concat()<br>    group_concat(字段名)可以作为一个输出字段来使用，<br>    表示分组之后，根据分组结果，使用group_concat()来放置每一组的某字段的值的集合<br> 例：    select 字段名1,group_concat(字段名2) from 表名 group by 字段名1；<br>     或 select 字段1,group_concat(字段2) from 表名 where 条件 group by 字段1;</p>
<p>·group by + 集合函数<br>     通过group_concat()的启发，我们既然可以统计出每个分组的某字段的值的集合，那么我们也可以通过集合函数来对这个值的集合做一些操作<br>例：    select 字段名1,group_concat(字段名2) from 表名 group by 字段名1;<br>    select 字段名1,count(*) from 表名 group by 字段名;</p>
<p>·group by + having<br>    having 条件表达式：用来分组查询后指定一些条件来输出查询结果<br>    本质：having作用和where一样，但having只能用于group by<br>例：    select gender,count(<em>) from 表名 group by 字段名 having count(</em>)&gt;数值;</p>
<p>·group by + with rollup<br>    with rollup的作用是：在最后新增一行，来记录当前列里所有记录的总和<br>例：    select 字段名1,count(*) from 表名 group by 字段名1 with rollup;<br>    select 字段名1,group_concat(字段名2) from 表名 group by 字段名1 with rollup;</p>
<p>完整的select语句顺序：<br>select distince *<br>from 表名<br>where …<br>group by … having …<br>order by …<br>limit start，count</p>
<p>select  获取查看<br>from    来自<br>where   后面加条件<br>group by   分组<br>having    对分组后的组进一步筛选<br>limit（m,n）   分页  m 起始位置  n 每页多少条数据<br>count（） 总揽条数 括号里可以加条件 总览某种数据<br>group_concat()  合并多个分组 括号里添加要合并的数据类型  </p>
<p>·where、having之间的区别和用法<br>作用的对象不同。WHERE 子句作用于表和视图，HAVING 子句作用于组。<br>聚合函数是比较where、having 的关键。<br>where、聚合函数、having 在from后面的执行顺序：where&gt;聚合函数(sum,min,max,avg,count)&gt;having<br>列出group by来比较二者。（）因where和having 在使用group by时问的最多）<br>若须引入聚合函数来对group by 结果进行过滤 则只能用having。<br>注意事项 ： </p>
<p>1、where 后不能跟聚合函数，因为where执行顺序大于聚合函数。 </p>
<p>2、where 子句的作用是在对查询结果进行分组前，将不符合where条件的行去掉，<br>即在分组之前过滤数据，条件中不能包含聚组函数，使用where条件显示特定的行。</p>
<p>3、having 子句的作用是筛选满足条件的组，即在分组之后过滤数据，条件中经常<br>包含聚组函数，使用having 条件显示特定的组，也可以使用多个分组标准进行分组。</p>
<p>分页：<br>分页：select *from 表名 limit 起始位置start,行数计数count;<br>   或  select *from 表名 where 条件 limit 起始位置start,行数计数count;</p>
<p>分页翻页<br>已知：每页显示m条数据，当前显示第n页<br>求总页数：此段逻辑后面会在python中实现<br>查询总条数p1<br>使用p1除以m得到p2<br>如果整除则p2为总数页<br>如果不整除则p2+1为总页数<br>求第n页的数据<br>例：   select <em>from 表名 limit (n-1)</em>m,m;</p>
<p>内连接查询：查询的结果为两个表匹配到的数据<br>语法1： inner join     on<br>select *from 左表名 inner join 右表名 on 左表名.两表相关联字段 = 右表名.两表相关联字段;<br>或 select *from 左表名 inner join 右表名 on 左表名.两表相关联字段 = 右表名.两表相关联字段<br> where 右表名.条件字段=值 and 左表名.条件字段&gt;值;</p>
<p>例： 如查看不同年级 每个年级都有谁 每个年级都有多少人<br>select class.name,group_concat(student.name),count(student.id)<br> from student inner join class on<br> class.id=student.class_id group by class.name;</p>
<p>语法2：<br>select 左表名.字段1,group_concat(右表名.字段1),count(右表名.两表相关联字段)<br> from 右表名 inner join 左表名 on<br> 左表名.两表相关联字段=右表名.两表相联关字段 group by 左表名.字段一;</p>
<p>右连接查询：  right join     on<br>查询的结果为两个表匹配到的数据，右表特有的数据，对于左表中不存在的数据使用null填充</p>
<p>语法：<br>select *from 右表名 right join 左表名 on 右表名.两表相关联字段 = 左表名.两表相关联字段;</p>
<p>左连接查询：   left join     on<br>查询的结果为两个表匹配到的数据，左表特有的数据，对于右表中不存在的数据使用null填充</p>
<p>语法：<br>select *from 左表名 left join 右表名 on 左表名.两表相关联字段 = 右表名.两表相关联字段;</p>
<p>查询表中 某字段重复数据的个数和最多的个数<br>select 字段1,count(*) as count from 表名 group by 字段1 having max(count);</p>
<p>select 字段1,count(*) as count from 表名 as a group by 字段1 having max(count) order by 字段1,count limit 0,1;</p>
<p>视图<br>MySql创建视图<br>(1).第一类：create view 视图名 as select * from 表名;</p>
<p>(2).第二类：create view 视图名 as select 字段,字段,字段 from 表名;</p>
<p>(3).第三类：create view 视图名v[vid,vname,vage] as select 字段,字段,字段 from 表名<br>删除视图<br>drop view 视图名；</p>
<p>mysql中去重          distinct</p>
<p>explain select 字段1 from 表名 where 字段1=值;     查看查找次数</p>
<p>create index 索引名 on 表名(相关字段);     加索引</p>
<p>drop index 索引名 on 表名;   删除索引</p>
<p>外键   alter table 表名1 add constraint 外键名字 foreign key(列名1) references 表名2(列名2)；</p>
<p>pymysql 交互：</p>
<h1 id="coding-UTF-8"><a href="#coding-UTF-8" class="headerlink" title="-- coding: UTF-8 --"></a>-<em>- coding: UTF-8 -</em>-</h1><h1 id="引入connect"><a href="#引入connect" class="headerlink" title="引入connect"></a>引入connect</h1><p>from pymysql import connect</p>
<h1 id="建立连接"><a href="#建立连接" class="headerlink" title="建立连接"></a>建立连接</h1><p>conn= connect(host=’localhost’,port=3306,database=’库名’,user=’用户名’,password=’密码’,charset=’utf8’)</p>
<h1 id="获取cursor对象"><a href="#获取cursor对象" class="headerlink" title="获取cursor对象"></a>获取cursor对象</h1><p>cur = conn.cursor()</p>
<h1 id="执行sql语句"><a href="#执行sql语句" class="headerlink" title="执行sql语句"></a>执行sql语句</h1><p>sql =”sql 语句命令”<br>cur.execute(sql)</p>
<h1 id="取出数据-fetchone-取一条数据-fetchall-取多条数据"><a href="#取出数据-fetchone-取一条数据-fetchall-取多条数据" class="headerlink" title="取出数据 fetchone 取一条数据   fetchall 取多条数据"></a>取出数据 fetchone 取一条数据   fetchall 取多条数据</h1><p>data=cur.fetchall()</p>
<h1 id="定义一个列表"><a href="#定义一个列表" class="headerlink" title="定义一个列表"></a>定义一个列表</h1><p>userlist = []<br>for i in data:<br>    # 定义一个字典来存放信息<br>    userdict = {}<br>    userdict[‘字段’] = i[-1]       # 索引位置信息<br>    userdict[‘字段’] = i[1]<br>    userdict[‘字段’] = i[2]<br>    userdict[‘带小数字段’] = float(i[3])<br>    userlist.append(userdict)  # 添加元素<br>    # print(data)</p>
<h1 id="输出"><a href="#输出" class="headerlink" title="输出"></a>输出</h1><p>print(userlist)</p>
<p>#关闭连接<br>cur.close()<br>conn.close()</p>
<h1 id="导入模块"><a href="#导入模块" class="headerlink" title="导入模块"></a>导入模块</h1><p>from pymysql import connect</p>
<h1 id="建立连接-1"><a href="#建立连接-1" class="headerlink" title="建立连接"></a>建立连接</h1><p>ck = connect(host=’localhost’,port=3306,database=’库名’,user=’用户名’,password=’密码’,charset=’utf8’)</p>
<h1 id="获取cursor对象-1"><a href="#获取cursor对象-1" class="headerlink" title="获取cursor对象"></a>获取cursor对象</h1><p>con = ck.cursor()</p>
<h1 id="执行sql语句-1"><a href="#执行sql语句-1" class="headerlink" title="执行sql语句"></a>执行sql语句</h1><p>con .execute(“sql 命令语句”)</p>
<h1 id="提交"><a href="#提交" class="headerlink" title="提交"></a>提交</h1><p>ck.commit()</p>
<p>‘’’<br>host             主机<br>localhost        本地主机<br>port             端口<br>database         数据库<br>user             用户<br>password         密码<br>charset          字符集<br>‘’’</p>
<p>select name from class where name=’二年级’;</p>
<p>后续待补。。。。。。</p>

        </div>
    

</div>
            
                
<div class="post">

    <div class="post-header index">
        <h1 class="title">
            <a href="/blog/2018/11/05/mongodb命令及介绍/">
                mongodb命令及介绍
            </a>
        </h1>
        <div class="post-info">
            
                <span class="date">2018-11-05</span>
            
            
            
        </div>
    </div>

    
        <div class="content">
            <h2 id="首先来了解下什么是MongoDB"><a href="#首先来了解下什么是MongoDB" class="headerlink" title="首先来了解下什么是MongoDB ?"></a>首先来了解下什么是MongoDB ?</h2><p>MongoDB 是由C++语言编写的，是一个基于分布式文件存储的开源数据库系统。</p>
<p>在高负载的情况下，添加更多的节点，可以保证服务器性能。</p>
<p>MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。</p>
<p>MongoDB 将数据存储为一个文档，数据结构由键值(key=&gt;value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档，数组及文档数组。</p>
<p><img src="https://www.runoob.com/wp-content/uploads/2013/10/crud-annotated-document.png" alt="img"></p>
<hr>
<h2 id="主要特点"><a href="#主要特点" class="headerlink" title="主要特点"></a>主要特点</h2><ul>
<li>MongoDB 是一个面向文档存储的数据库，操作起来比较简单和容易。</li>
<li>你可以在MongoDB记录中设置任何属性的索引 (如：FirstName=”Sameer”,Address=”8 Gandhi Road”)来实现更快的排序。</li>
<li>你可以通过本地或者网络创建数据镜像，这使得MongoDB有更强的扩展性。</li>
<li>如果负载的增加（需要更多的存储空间和更强的处理能力） ，它可以分布在计算机网络中的其他节点上这就是所谓的分片。</li>
<li>Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记，可轻易查询文档中内嵌的对象及数组。</li>
<li>MongoDb 使用update()命令可以实现替换完成的文档（数据）或者一些指定的数据字段 。</li>
<li>Mongodb中的Map/reduce主要是用来对数据进行批量处理和聚合操作。</li>
<li>Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录，将key与value传给Reduce函数进行处理。</li>
<li>Map函数和Reduce函数是使用Javascript编写的，并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。</li>
<li>GridFS是MongoDB中的一个内置功能，可以用于存放大量小文件。</li>
<li>MongoDB允许在服务端执行脚本，可以用Javascript编写某个函数，直接在服务端执行，也可以把函数的定义存储在服务端，下次直接调用即可。</li>
<li>MongoDB支持各种编程语言:RUBY，PYTHON，JAVA，C++，PHP，C#等多种语言。</li>
<li>MongoDB安装简单。</li>
</ul>
<p>下面是一些个人对于mongo db命令 理解的笔记：</p>
<p>mongoDB 命令：</p>
<p>连接-打开mongodb数据库：    monggo</p>
<p>查看当前所在库：显示当前使用的数据库名称    db.getName() 或 db;</p>
<p>删当前使用的数据库    db.dropDatabase()</p>
<p>修复当前数据库    db.repairDatabase()</p>
<p>当前数据库版本    db.version()</p>
<p>查看当前数据库的链接机器地址 db.getMongo()</p>
<p>显示当前数据库状态，包含数据库名称，集合个数，当前数据库大小 …    db.stats()</p>
<p>查看数据库中有那些个集合（表）：    db.getCollectionNames()</p>
<p>查看所有库：    show dbs;</p>
<p>进入数据库（没有的话自动创建）自动创建：    use 库名;</p>
<p>删除当前的数据库：    db.dropDatabase()</p>
<p>创建集合：    db.createCollection(“集合名”);</p>
<p>查看所有集合：    show collections;</p>
<p>插入数据    db.集合名.insert({“”:””,””:””});</p>
<p>插入数据小案例：<br>单条写入数据：<br>db.posts.insert({“title”:”我的第一篇博客”,”content”:”我要开始写博客了”});<br>db.posts.insert({“title”:”我的第二篇博客”,”content”:”写点什么好呢”});<br>多条写入：加Many方法 或 所有的key不加引号<br>db.posts.insertMany([{“title”:”我的第三篇博客”},{“content”:”今天吃什么”}]);<br>遍历写入数据：(支持css语法，var可加可不加)<br>for(var i=4;i&lt;=10;i++){db.posts.insert({“title”:”我的第”+i+”篇博客”})};</p>
<p>查看集合内所有数据：    db.集合名.find();</p>
<p>条件查找：<br>格式：db.集合名.find({“字段名”:{条件}});<br>$gte    大于等于<br>$gt    大于<br>$lte    小于等于<br>$lt    小于<br>$eq    等于<br>$ne    不等于</p>
<p>正则表达式：/k/,/^k/</p>
<p>按照字段取唯一的值（可去重）：    db.posts.distinct(‘字段名’);</p>
<p>指定提取的字段（投影）(value值为布尔类型true/1,flase/0)：<br>语法：    db.字段名.find({},{‘字段名’:true,’字段名2’:1});</p>
<p>案例数据：<br>db.posts.insert({‘title’ : ‘怪物猎人世界评测’, ‘rank’ : 2, ‘tag’ : ‘game’ });<br>db.posts.insert({‘title’ : ‘纸片马里奥试玩体验’, ‘rank’ : 1, ‘tag’ : ‘game’ });<br>db.posts.insert({‘title’ : ‘Ubuntu16LTS的安装’, ‘rank’ : 3, ‘tag’ : ‘it’ });<br>db.posts.insert({‘title’ : ‘信长之野望大志销量突破10000’, ‘rank’ : 4, ‘tag’ : ‘game’ });<br>db.posts.insert({‘title’ : ‘Ruby的开发效率真的很高吗’, ‘rank’ : 7, ‘tag’ : ‘it’ });<br>db.posts.insert({‘title’ : ‘塞尔达传说最近除了DLC’, ‘rank’ : 4, ‘tag’ : ‘game’ });<br>db.posts.insert({‘title’:’惊！骑士发生重大交易’, ‘istop’:true});</p>
<p>条件查询：<br>db.posts.find({‘rank’:{$gte:4}});    查询rank大于等于4的记录<br>db.posts.find({‘rank’:{$gt:4}});    查询rank大于4的记录<br>db.posts.find({‘rank’:{$lte:4}});    查询rank小于等于4的记录<br>db.posts.find({‘rank’:{$lt:4}});    查询rank小于4的记录<br>db.posts.find({‘rank’:{$eq:4}});    查询rank等于4的记录<br>db.posts.find({‘rank’:{$ne:4}});    查询rank不等于4的记录</p>
<p>正则查找：<br>db.posts.find({‘title’:/u/});    查找title里面含有u的记录<br>db.posts.find({‘title’:/U/});    查找title里面开头是U的记录</p>
<p>复杂条件查询文档 -格式：<br>与    db.集合名.find({“”:””,””:””});<br>or或    db.集合名.find({$or:[{“”:””},{“”:””}:{“”:””}]});<br>in在…里    db.集合名.find({‘字段名’:{$in:[要找到的值]}});<br>判断该字段是否存在    db.posts.find(‘字段名’：{$sexists:true});</p>
<p>实战案例：<br>与    db.posts.find({‘title’:/u/,’rank’:{$gte:5}});<br>or或    db.posts.find({$or:[{‘title’:/u/},{‘rank’:{$gte:5}}]});<br>in在…里    db.posts.find({‘rank’:{$in:[1,2,3]}});<br>按照字段tag取唯一的值    db.posts.distinct(‘tag’);<br>判断该字段是否存在    db.posts.find(‘istop’：{$exists:true});</p>
<p>指定提取的字段（投影）(value值为布尔类型true/1,flase/0)    db.posts.find({‘title’:/u/},{‘title’:true,’rank’:1,’_id’:0});</p>
<p>其他方法(管道):<br>sort()    排序<br>limit()    限制条数（分页）<br>skip()    跳过文档<br>格式：<br>db.集合名.find({}).sort({‘字段’:1});    正序<br>db.集合名.find({}).sort({‘字段’:1}).limit(3);    正序前三条<br>db.集合名.find({}).sort({‘字段’:1});</p>
<p>实战案例：<br>db.posts.find({}).sort({‘rank’:1});</p>
<p>db.posts.find({}).sort({‘rank’:-1,’title’:-1});</p>
<p>db.posts.find({}).sort({‘rank’:-1}).limit(3);</p>
<p>db.posts.find({}).sort({‘rank’:-1}).skip(3).limit(3);</p>
<p>更新文档：<br>update(<filter>,<update>,<options>)    —filter=条件、update=更新内容、options=加{multi:true}更新所有（不加只更新一条）</options></update></filter></p>
<p>db.posts.findOne（{“”:””}）    指定查看一条</p>
<p>实战：<br>db.posts.findOne({‘title’:’怪物猎人世界评测’})；    指定查看<br>db.posts.update({‘title’:’怪物猎人世界评测’},{$set:{‘rank’:16}});    保留原有字段更新rank字段<br>db.posts.update({‘title’:’怪物猎人世界评测’},{‘rank’:19});    冲掉非_id字段换成rank字段<br>db.posts.update({“tag”:”it”},{$set:{“rank”:199}},{multi:true});    多条更新</p>
<p>文档删除：</p>
<p>格式 ： db.集合名.remove(<query>,{justOne:true})<br>query：    可选，条件<br>justOne: 可选，如果设为true或1 表示删除一条 默认False，表示删除多条</query></p>
<p>实战用法：<br>移除所有文档    db.集合名.remove({});<br>移除指定文档    db.集合名.remove({‘字段’:{条件}},{justOne:true});</p>
<p>统计个数：<br>.count() 用于统计集合中的文档条数</p>
<p>实战用法：<br>db.集合名.find({“”:{条件}}).count()<br>db.集合名.count({“”:{条件}})</p>
<p>聚合：<br>aggregate()    聚合(aggregate)是基于数据处理的聚合管道，每个文档通过一个由多个阶段（stage）组成的管道，<br>可以对每个阶段进行分组、过滤等功能，然后经过一系列的处理，输出相应的结果<br>$group    将集合中的文档分组，可用于统计结果<br>$match    过滤数据，只输出符合条件的文档<br>$group： 将集合中的文档分组， 可用于统计结果（$group是所有聚合命令中用的最多的一个命令，用来将集合中的文档分组，可用于统计结果）<br>$match： 过滤数据， 只输出符合条件的文档<br>$project： 修改输入文档的结构， 如重命名、 增加、 删除字段、 创建计算结果<br>$sort： 将输入文档排序后输出<br>$limit： 限制聚合管道返回的?档数<br>$skip：    跳过指定数量的?档， 并返回余下的?档</p>
<p>注意点：<br>db.db_name.aggregate是语法，所有的管道命令都需要写在其中<br>_id 表示分组的依据，按照哪个字段进行分组，需要使用$gender表示选择这个字段进行分组</p>
<p>在管道中排序，按先排序后显示操作，管道自左而右执行</p>
<p>常用表达式：    表达式：处理输文档并输出 语法：表达式:’$列名’ 常用表达式:<br>$sum： 计算总和， $sum:1 表示以1倍计数</p>
<p>$avg： 计算平均值<br>$min： 获取最小值<br>$max： 获取最大值<br>$push： 在结果文档中插入值到1个数组中</p>
<p>实战语法：<br>db.集合名.aggregate([ { $group:{ ‘_id’:’$字段分组’, 获取的信息变量名:{$push:’$要获取的字段名’} } } ]);<br>单位数    $sum:1    每个单位为1</p>
<p>实战案例数据：<br>db.students.insert({“name” : “郭靖”, “hometown” : “蒙古”, “age” : 20, “gender” : true });<br>db.students.insert({“name” : “黄蓉”, “hometown” : “桃花岛”, “age” : 18, “gender” : false })<br>db.students.insert({“name” : “华筝”, “hometown” : “蒙古”, “age” : 18, “gender” : false });<br>db.students.insert({“name” : “黄药师”, “hometown” : “桃花岛”, “age” : 40, “gender” : true });<br>db.students.insert({“name” : “段誉”, “hometown” : “大理”, “age” : 16, “gender” : true });<br>db.students.insert({“name” : “段王爷”, “hometown” : “大理”, “age” : 45, “gender” : true });<br>db.students.insert({“name” : “洪七公”, “hometown” : “华山”, “age” : 18, “gender” : true });</p>
<p>实战演习：<br>db.students.remove({‘rank’:{$lt:4}},{justOne:true});<br>db.students.remove({});</p>
<p>db.students.find({‘rank’:{$lt:4}}).count();<br>db.students.count({‘rank’:{$lt:4}});</p>
<p>1 按照某个字段进行分组<br>$group是所有聚合命令中用的最多的一个命令，用来将集合中的文档分组，可用于统计结果</p>
<p>db.students.aggregate([ { $group:{‘_id’:’$gender’} } ]);<br>db.db_name.aggregate是语法，所有的管道命令都需要写在其中<br>_id 表示分组的依据，按照哪个字段进行分组，需要使用$gender表示选择这个字段进行分组<br>db.students.aggregate([ { $group:{‘_id’:’$gender’, counter:{$sum:1} } } ]);<br>$sum:1 表示把每条数据作为1进行统计，统计的是该分组下面数据的条数</p>
<p>2 group by null<br>当我们需要统计整个文档的时候，$group 的另一种用途就是把整个文档分为一组进行统计</p>
<p>db.students.aggregate([{$group:{‘id’:null,counter:{$sum:1}}}]);<br>_id:null 表示不指定分组的字段，即统计整个文档，此时获取的counter表示整个文档的个数</p>
<p>3 数据透视<br>正常情况在统计的不同姓名的数据的时候，需要知道所有的name，需要逐条观察，如果通过某种方式把所有的name放到一起，那么此时就可以理解为数据透视<br>db.students.aggregate([{$group:{‘_id’:null,’name’:{$push:’$name’}}}]);</p>
<p>使用$$ROOT可以将整个文档放入数组中<br>db.students.aggregate([{$group:{‘_id’:null,’name’:{$push:’$$ROOT’}}}]);</p>
<p>聚合的高级应用：</p>
<p>实战数据：<br>db.infos.insertMany([<br>{ “country” : “china”, “province” : “sh”, “userid” : “a” },<br>{ “country” : “china”, “province” : “sh”, “userid” : “b” },<br>{ “country” : “china”, “province” : “sh”, “userid” : “c” },<br>{ “country” : “china”, “province” : “sh”, “userid” : “d” },<br>{ “country” : “china”, “province” : “tj”, “userid” : “a” },<br>{ “country” : “china”, “province” : “tj”, “userid” : “b” },<br>{ “country” : “china”, “province” : “tj”, “userid” : “c” },<br>{ “country” : “china”, “province” : “bj”, “userid” : “a” },<br>{ “country” : “china”, “province” : “bj”, “userid” : “b” }<br>]);</p>
<p>$match:</p>
<p>实战数据：<br>db.orders.insertMany([<br>{“cust_id”:”A123”,”amount”:500,”status”:”A”},<br>{“cust_id”:”A123”,”amount”:250,”status”:”A”},<br>{“cust_id”:”B212”,”amount”:200,”status”:”A”},<br>{“cust_id”:”A123”,”amount”:300,”status”:”D”},<br>{“cust_id”:”A126”,”amount”:360,”status”:”U”},<br>{“cust_id”:”A136”,”amount”:360,”status”:”W”},<br>{“cust_id”:”A136”,”amount”:360,”status”:”A”},<br>{“cust_id”:”A139”,”amount”:660,”status”:”A”},<br>{“cust_id”:”A139”,”amount”:960,”status”:”A”}]);</p>
<p>实战案例：<br>==按照cust_id字段进行分组==<br>&gt; db.orders.aggregate([ { $group:{‘_id’:’$cust_id’} } ]);<br>==只取status等于A的数据<br>&gt; db.orders.aggregate([ { $match:{‘status’:’A’} } ]);<br>==只取status等于A的数据，然后再按照cust_id字段进行分组，统计每个分组下的消费总额amount<br>&gt; db.orders.aggregate([ { $match:{‘status’:’A’} },{ $group:{‘_id’:’$cust_id’,’total’:{$sum:’$amount’} } } ]);</p>
<p>$project:</p>
<p>索引:<br>作用：加快查询速度,进行数据的去重</p>
<p>默认情况下_id是集合的索引</p>
<p>创建索引方法：<br>语法：    db.集合名.createIndex({‘字段’:1/-1})<br>注意：从 mongoDB 3.0 开始，ensureIndex 被废弃，今后都仅仅是 createIndex 的一个别名。<br>db.集合.createIndex({属性:1})1表示升序， -1表示降序</p>
<p>索引查看方法：<br>语法：    db.集合名.getIndexes()</p>
<p>添加唯一索引：<br>语法：    db.集合名.ensureIndex({字段:1},{unique:true});<br>db.集合名.createIndex({字段:1},{unique:true});</p>
<p>删除索引方法：<br>语法：    db.集合名.dropIndex({‘索引名称’:1/-1})</p>
<p>备份的相关操作：<br>作用：保证数据库安全，主要用于灾难处理<br>mongo端口号：27017</p>
<p>备份:    保证数据库安全，主要用于灾难处理<br>备份的语法：<br>mongodump -h dbhost -d dbname -o dbdirectory<br>mongodump -h 服务器地址也可以指定端口号 -d 要备份的库名 -o 要备份的地址路径</p>
<p>示例：mongodump -h 192.168.196.128:27017 -d test1 -o ~/Desktop/test1bak</p>
<p>恢复:语法：<br>mongorestore -h 服务器地址也可以指定端口号 -d 要恢复数据库名(要和备份之前不一样) –dir 备份数据所在位置<br>mongorestore -h dbhost -d dbname –dir dbdirectory</p>
<p>示例：mongorestore -h 192.168.196.128:27017 -d test2 –dir ~/Desktop/test1bak/test1</p>
<p>导出：<br>导出：用于和其他平台进行交互对接，将数据导出成指定格式文件进行使用，<br>比如数据分析常用的csv文件 用于给非计算机行业的用户查看数据，对于他们来说csv文件(打开之后是电子表格)更方便<br>导出语法:<br>mongoexport -h 服务器地址，也可以指定端口号 -d 数据库名 -c 集合名 -o 导出地址/文件名 –type 文件类型(默认json) -f 指定导出哪些字段，默认全部，导出成csv文件是必须指定</p>
<p>mongoexport -h dbhost -d dbname -c colname -o filename –type json/csv -f field</p>
<p>示例：mongoexport -h 192.168.196.128:27017 -d test2 -c col1 -o test1_col1 [–type csv -f name,age,number]</p>
<p>导入：语法:<br>mongoimport -h 服务器地址，也可以指定端口号 -d 数据库名 -c 集合名 –file 导入文件路径 –type 文件类型 -f 要导入的字段</p>
<p>mongoimport -h dbhost -d dbname -c colname –file filename –type json/csv -f field</p>
<p>示例：mongoimport -h 127.0.0.1:27017 -d abcde -c infos –file c:\Users\wzh\aa\abc_csv –type csv -f title,description</p>
<p>关键词释义：<br>-c: 集合名<br>-h： 服务器地址， 也可以指定端口号<br>-d： 需要备份的数据库名称<br>-o： 备份的数据存放位置， 此目录中存放着备份出来的数据<br>–type: 文件类型，默认json格式，可选数据类型json，csv<br>-f: 需要导出的字段,导出为json格式的数据时可以不指定导出哪些字段，默认全部，导出成csv文件是必须指定<br>–type: 文件类型，默认json格式，可选数据类型json，csv<br>–dir： 备份数据所在位置</p>

        </div>
    

</div>
            
        </section>
    </div>
</div>



    <div class="row">
        <div class="col-sm-12">
            <div class="wrap-pagination">
                <a class="" href="/blog/page/4/">
                    <i class="fa fa-chevron-left" aria-hidden="true"></i>
                </a>
                <a class="" href="/blog/page/6/">
                    <i class="fa fa-chevron-right" aria-hidden="true"></i>
                </a>
            </div>
        </div>
    </div>




</div>

<!-- Footer -->
<div class="push"></div>

<footer class="footer-content">
    <div class="container">
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-6 col-lg-6 footer-about">
                <h2>About</h2>
                <p>
                    This theme was developed by <a href="https://github.com/klugjo">Jonathan Klughertz</a>. The source code is available on Github. Create Websites. Make Magic.
                </p>
            </div>
            
    <div class="col-xs-6 col-sm-6 col-md-3 col-lg-3 recent-posts">
        <h2>Recent Posts</h2>
        <ul>
            
            <li>
                <a class="footer-post" href="/blog/2019/10/25/tars框架环境基础搭建/">tars框架环境基础搭建</a>
            </li>
            
            <li>
                <a class="footer-post" href="/blog/2019/10/20/认识tars框架/">认识tars框架</a>
            </li>
            
            <li>
                <a class="footer-post" href="/blog/2019/10/05/redis数据迁移备份与恢复/">redis数据迁移备份与恢复</a>
            </li>
            
            <li>
                <a class="footer-post" href="/blog/2019/09/21/负载均衡的5种策略/">负载均衡的5种策略</a>
            </li>
            
        </ul>
    </div>



            
        </div>
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
                <ul class="list-inline footer-social-icons">
                    
                    <li class="list-inline-item">
                        <a href="https://github.com/klugjo/hexo-theme-alpha-dust">
                            <span class="footer-icon-container">
                                <i class="fa fa-github"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://twitter.com/?lang=en">
                            <span class="footer-icon-container">
                                <i class="fa fa-twitter"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://www.facebook.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-facebook"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://www.instagram.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-instagram"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://dribbble.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-dribbble"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://plus.google.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-google-plus"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://www.behance.net/">
                            <span class="footer-icon-container">
                                <i class="fa fa-behance"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="https://500px.com/">
                            <span class="footer-icon-container">
                                <i class="fa fa-500px"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="mailto:test@example.com">
                            <span class="footer-icon-container">
                                <i class="fa fa-envelope-o"></i>
                            </span>
                        </a>
                    </li>
                    
                    
                    <li class="list-inline-item">
                        <a href="\#">
                            <span class="footer-icon-container">
                                <i class="fa fa-rss"></i>
                            </span>
                        </a>
                    </li>
                    
                </ul>
            </div>
        </div>
        <div class="row">
            <div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
                <div class="footer-copyright">
                    @Untitled. All right reserved | Design & Hexo <a href="http://www.codeblocq.com/">Jonathan Klughertz</a>
                </div>
            </div>
        </div>
    </div>
</footer>

<!-- After footer scripts -->

<!-- jQuery -->
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>

<!-- Tween Max -->
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.18.5/TweenMax.min.js"></script>

<!-- Gallery -->
<script src="//cdnjs.cloudflare.com/ajax/libs/featherlight/1.3.5/featherlight.min.js" type="text/javascript" charset="utf-8"></script>

<!-- Custom JavaScript -->
<script src="/blog/js/main.js"></script>

<!-- Disqus Comments -->



</body>

</html>